最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)在線SQL編程最新完整版

 更新時間:2022年06月23日 11:10:57   作者:派大星i  
這篇文章主要介紹了Java實現(xiàn)在線SQL編程,在使用JDBC來進(jìn)行數(shù)據(jù)庫的操作,在使用時由于對其方法并不是全部了解,所以需要邊看源碼邊改善功能,感興趣的朋友跟隨小編一起看看吧

前言: 由于前段時間,項目組長分配的任務(wù)是要完成一個在線編寫SQL并要實現(xiàn)查詢功能的需求,最終需要將查詢到的數(shù)據(jù)以JSON格式顯示到響應(yīng)數(shù)據(jù)的區(qū)域,以供操作者進(jìn)行查看,一開始拿到需求時想著直接使用Mybatis進(jìn)行操作不就可以了,完全沒必要大費周章,因為在MyBatis中有個拼接SQL的語法,可以使用${sql}來進(jìn)行執(zhí)行輸入的SQL語句,但是實際操作起來并不是想象中的那么簡單,因為使用MyBatis會將數(shù)據(jù)源固定在本項目所使用的數(shù)據(jù)庫,而不可以進(jìn)行數(shù)據(jù)源之間的切換,無法進(jìn)行其他數(shù)據(jù)源中表的查詢操作 ?,所以在實現(xiàn)過程也是相當(dāng)艱難曲折...

?? 難度分析

在線執(zhí)行SQL語句的查詢主要的難點分為以下幾點:其一則是對JDBC的部分的API理解的不夠透徹,導(dǎo)致在實現(xiàn)某些工鞥是并不是想象中的順利;其二在于對于查詢部分屬性的SQL語句該如何使用Java進(jìn)行實現(xiàn),是將輸入的字符串進(jìn)行分割再拼接還是使用直接整條語句的查詢操作;其三則是用戶可以動態(tài)的切換數(shù)據(jù)源,并且對相應(yīng)數(shù)據(jù)源下的表進(jìn)行查詢操作,如果使用Mybatis進(jìn)行SQL的查詢操作則無法進(jìn)行數(shù)據(jù)源的切換,只能查詢所在微服務(wù)項目所連接的數(shù)據(jù)庫進(jìn)行查詢,否則無法進(jìn)行相應(yīng)的操作,即會出現(xiàn)該數(shù)據(jù)庫下并不存在所查詢的某張數(shù)據(jù)庫表的錯誤信息 ?

?? 項目回顧(在線編寫SQL查詢)

?? 最終效果演示

?? 技術(shù)選型:

  • ?? SpringBoot
  • ?? MyBatis-Plus
  • ?? JDBC
  • ?? Vue
  • ?? 代碼編輯器monaco-editor

?? 需求分析

使用者在頁面可以選擇切換需要操作的數(shù)據(jù)源,并在編輯區(qū)域內(nèi)輸入SQL語句進(jìn)行查詢,查詢語句可以是全表查詢表中所有字段或者根據(jù)所需查詢指定某幾列字段對應(yīng)的值,點擊查詢之后即可在響應(yīng)數(shù)據(jù)之后以JSON的格式將查詢到的每一條數(shù)據(jù)封裝一個對象最后顯示到響應(yīng)數(shù)據(jù)區(qū)域以供操作者進(jìn)行觀看以達(dá)到可視化工具的效果。

?? 項目搭建

① 引入項目所需要的相關(guān)Maven依賴

<!--SpringBoot相關(guān)依賴-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>commons-lang</groupId>
  <artifactId>commons-lang</artifactId>
  <version>2.6</version>
</dependency>
<!--servlet-api相關(guān)依賴-->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>servlet-api</artifactId>
  <version>2.5</version>
  <scope>provided</scope>
</dependency>
<!--MySQL驅(qū)動相關(guān)依賴-->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.28</version>
</dependency>

② 編寫配置文件

server:
  port: 8080
spring:
  datasource:
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/data_source?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai

③ 創(chuàng)建Controller前端控制器

	@PostMapping("/dynamic-query")
	@ApiOperation(value = "動態(tài)執(zhí)行SQL")
	public Result<?> dynamicQuery(@RequestBody DynamicQuery dynamicQuery){
		List<HashMap<Object,Object>> res = null;
		BladeVisualDb visualDb = bladeVisualDbService.getOne(new QueryWrapper<BladeVisualDb>().eq("id", dynamicQuery.getId()));
		List<HashMap<String,Object>> result = ConnectBySql.connAndExecSql(visualDb.getUrl(), visualDb.getDriverClass(), visualDb.getUsername(), visualDb.getPassword(),dynamicQuery.getSql());
		return Result.ok(result);
	}

④ 探究 JDBC中ResultSet中的方法

  • next()

解釋: 將光標(biāo)從其當(dāng)前位置向前移動一行。 ResultSet 游標(biāo)最初位于第一行之前;第一次調(diào)用 next 方法使第一行成為當(dāng)前行;第二次調(diào)用使第二行成為當(dāng)前行,依此類推。實則對查詢到的數(shù)據(jù)進(jìn)行遍歷操作

  • getString(String columnLabel)

解釋: 根據(jù)表中對應(yīng)的列名稱來查詢到該列對應(yīng)到的數(shù)據(jù)

  • getMetaData()

解釋: 獲取某張表中列的數(shù)量、類型和列名稱

  • findColumn(String columnLabel)

解釋: 返回某個列的索引值即下標(biāo)

⑤ 獲取所有的數(shù)據(jù)源

因為使用者是可以動態(tài)的選擇數(shù)據(jù)源從而來對表中的數(shù)據(jù)進(jìn)行相關(guān)操作,所以首先要查詢出可供連接的數(shù)據(jù)源

	 /**
	  * 下拉數(shù)據(jù)源列表
	  * @return
	  */
	@ApiOperation(value = "下拉列表")
	@GetMapping("/db-list")
	public Result<?> list(){
		List<BladeVisualDb> bladeVisualDbs = bladeVisualDbService.list();
		return Result.ok(bladeVisualDbs);
	}

⑥ 實現(xiàn)執(zhí)行查詢邏輯

首先執(zhí)行查詢有兩種方式:所有字段的全查詢即select * from xx 或者 查詢指定字段即select xx from xx

  • 所有字段的全查詢即select * from xx

在進(jìn)行所有字段的查詢時,由于無法得知需要查詢的表中有什么字段,所以首先需要對輸入的SQL字符串進(jìn)行判斷是否是全字段查詢,然后即可獲取查詢表中的所有字段,然后再一一的進(jìn)行查詢出字段對應(yīng)的值即可,此操作也是需要對輸入SQL字符串進(jìn)行分割的,拿出所有插敘的表名即可。

ResultSet resultSet = stmt.executeQuery(sql);
//如果輸入的SQL屬于select * 操作
if (sql.contains("*")){
  List<String> list = new ArrayList<>();
  //獲取SQL中需要查詢的表的結(jié)構(gòu)
  ResultSetMetaData metaData = resultSet.getMetaData();
  int columnCount = metaData.getColumnCount();
  for (int i = 1; i <= columnCount; i++) {
    log.info("屬性列   ======>{}",metaData.getColumnName(i));
    //獲取表中的所有列
    list.add(metaData.getColumnName(i));
  }
  while (resultSet.next()){
    HashMap<String,Object> hashMap = new HashMap<>();
    for (String index : list) {
      //根據(jù)列名稱查詢出該列對應(yīng)的數(shù)據(jù)
      String rs = resultSet.getString(index);
      //將其放入列和值存放HashMap中
      hashMap.put(index,rs);
      //將多個HashMap合并成一個Map
      hashMap.putAll(hashMap);
    }
    res.add(hashMap);
  }
}
  • 查詢指定字段即select xx from xx

在使用JDBC進(jìn)行指定字段查詢時需要對輸入的SQL字符串進(jìn)行分割后將所需要查詢到的字段再使用JDBC中的getString(String columnName)進(jìn)行查詢字段對應(yīng)的值

    /**
     * 將SQL語句進(jìn)行拆分
     * @param sql
     * @return
     */
    @NotNull
    private static List<String> getString(String sql) {
        List<String> list = new ArrayList<>();
        String str = sql.substring(0, sql.indexOf("from"));
        String realSql = str.replace("select", "").trim();
        if (realSql.contains(",")){
            String[] split = realSql.split(",");
            for (String s : split) {
                list.add(s);
            }
        }else {
            list.add(realSql);
        }
        return list;
    }

隨后將分割完成的SQL存放到List集合中再進(jìn)行查詢操作

ResultSet resultSet = stmt.executeQuery(sql);
while (resultSet.next()){
  HashMap<String,Object> hashMap = new HashMap<>();
  List<String> str = getString(sql);
  for (String index : str) {
    String rs = resultSet.getString(index);
    hashMap.put(index,rs);
    hashMap.putAll(hashMap);
  }
  res.add(hashMap);
}

經(jīng)過對操作者輸入的SQL即可完成對表的查詢操作,由于所要實現(xiàn)的是可動態(tài)切換數(shù)據(jù)源從而進(jìn)行相關(guān)的查詢操作,所以在此操作邏輯中首先需要連接數(shù)據(jù)庫,后再對輸入的SQL進(jìn)行分割查詢等操作。合并后的完整代碼:

    /**
     * 連接數(shù)據(jù)庫并根據(jù)輸入的SQL語句查詢數(shù)據(jù)
     * @param url
     * @param driverClass
     * @param username
     * @param password
     * @param sql
     * @return
     */
    public static List<HashMap<String,Object>> connAndExecSql(String url, String driverClass, String username, String password, String sql) {
        Boolean result = false;
        Connection conn = null;
        Statement stmt = null;
        List<HashMap<String,Object>> res = new ArrayList<>();

        try {
            Class.forName(driverClass);
            System.out.println("------------連接數(shù)據(jù)庫-----------");
            conn = DriverManager.getConnection(url,username,password);
            stmt = conn.createStatement();

            ResultSet resultSet = stmt.executeQuery(sql);
            //如果輸入的SQL屬于select * 操作
            if (sql.contains("*")){
                List<String> list = new ArrayList<>();
                //獲取SQL中需要查詢的表的結(jié)構(gòu)
                ResultSetMetaData metaData = resultSet.getMetaData();
                int columnCount = metaData.getColumnCount();
                for (int i = 1; i <= columnCount; i++) {
                    log.info("屬性列   ======>{}",metaData.getColumnName(i));
                    //獲取表中的所有列
                    list.add(metaData.getColumnName(i));
                }
                while (resultSet.next()){
                    HashMap<String,Object> hashMap = new HashMap<>();
                    for (String index : list) {
                        //根據(jù)列名稱查詢出該列對應(yīng)的數(shù)據(jù)
                        String rs = resultSet.getString(index);
                        //將其放入列和值存放HashMap中
                        hashMap.put(index,rs);
                        //將多個HashMap合并成一個Map
                        hashMap.putAll(hashMap);
                    }
                    res.add(hashMap);
                }
            }else {
                while (resultSet.next()){
                    HashMap<String,Object> hashMap = new HashMap<>();
                    List<String> str = getString(sql);
                    for (String index : str) {
                        String rs = resultSet.getString(index);
                        hashMap.put(index,rs);
                        hashMap.putAll(hashMap);
                    }
                    res.add(hashMap);
                }
            }
            //完成連接數(shù)據(jù)庫
            stmt.close();
            conn.close();
            System.out.println("查詢連接結(jié)束");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }catch (SQLException e){
            e.printStackTrace();
        }
        return res;
    }

    /**
     * 將SQL語句進(jìn)行拆分
     * @param sql
     * @return
     */
    @NotNull
    private static List<String> getString(String sql) {
        List<String> list = new ArrayList<>();
        String str = sql.substring(0, sql.indexOf("from"));
        String realSql = str.replace("select", "").trim();
        if (realSql.contains(",")){
            String[] split = realSql.split(",");
            for (String s : split) {
                list.add(s);
            }
        }else {
            list.add(realSql);
        }
        return list;
    }

⑦ Vue前端引入monaco-editor組件進(jìn)行編寫SQL語句

?? 項目總結(jié)

在使用JDBC來進(jìn)行數(shù)據(jù)庫的操作,在使用時由于對其方法并不是全部了解,所以需要邊看源碼邊改善功能,因此遇到問題時才會感覺到腦中知識儲備的不足,目前只是實現(xiàn)了查詢操作,還未完善CRUD全部過程的操作。

到此這篇關(guān)于Java實現(xiàn)在線SQL編程的文章就介紹到這了,更多相關(guān)java SQL編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

汉寿县| 翁牛特旗| 高阳县| 黔西| 隆化县| 阿拉尔市| 丁青县| 平湖市| 桦甸市| 涟水县| 绩溪县| 泗洪县| 大化| 鸡泽县| 顺平县| 边坝县| 隆化县| 买车| 雅安市| 和硕县| 衡阳县| 杭州市| 泌阳县| 瓮安县| 上杭县| 吴堡县| 原阳县| 朝阳区| 淳安县| 浦江县| 永丰县| 大足县| 方城县| 钟山县| 石嘴山市| 康乐县| 昌平区| 峨边| 阳高县| 宁城县| 百色市|