1、原生JDBC的缺陷

在 JDBC 笔记(一):JDBC的开发步骤 中,提到原生JDBC查询数据库的开发步骤,不难看出用原生的JDBC查询数据库有以下缺点:

1、代码重复

原生JDBC,获取数据库连接、创建Statement对象步骤,每次查询数据库都需要创建并获取1.

2、资源管理

数据库连接资源需要手动关闭。

3、结果集处理

添加数据库的结果集需要映射到实体对象中的逻辑处理。

4、SQL耦合

SQL硬编码在代码逻辑中。

2、JDBC封装优化

针对上述缺陷,对原生JDBC做简单封装。JDBC封装是基于JDBC 笔记(一):JDBC的开发步骤中的原生JDBC的优化。

2.1、代码重复、资源管理的优化

创建jdbc工具类,封装获取连接,关闭资源的方法。

1 import java.sql.*;

2 import java.util.Objects;

3

4 public class JdbcUtils {

5

6 private static final String URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8";

7 private static final String USERNAME = "root";

8 private static final String PASSWORD = "root";

9 public static Connection conn = null;

10 public static PreparedStatement ps = null;

11

12 /**

13 * 数据库连接

14 * @return

15 */

16 public static Connection getConnection() {

17 if (conn == null) {

18 try {

19 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);

20 } catch (SQLException e) {

21 e.printStackTrace();

22 }

23 }

24 return conn;

25 }

26

27 /**

28 * 关闭资源

29 * @param conn

30 * @param sta

31 * @param rs

32 */

33 public static void close(Connection conn, Statement sta, ResultSet rs) {

34 try {

35 // 关闭ResultSet

36 if (Objects.nonNull(rs)) {

37 rs.close();

38 }

39 // 关闭Statement

40 if (Objects.nonNull(sta)) {

41 sta.close();

42 }

43 // 关闭Connection

44 if (Objects.nonNull(conn)) {

45 sta.close();

46 }

47 } catch (SQLException e) {

48 e.printStackTrace();

49 }

50 }

51 }

JDBC操作可简化如下:

1 public void getUserInnfo() throws Exception {

2 // 获取连接

3 Connection conn = JdbcUtils.getConnection();

4

5 String querySql = " select * from user where id = ?";

6 PreparedStatement ps = conn.prepareStatement(querySql);

7 ps = conn.prepareStatement(querySql);

8 ps.setInt(1, 101);

9 ResultSet rs = ps.executeQuery();

10 while(rs.next()) {

11 System.out.println("用户名称:" + rs.getString("name"));

12 }

13

14 // 关闭资源

15 JdbcUtils.close(conn, ps, rs);

16 }

2.2、SQL耦合的优化

对SQL耦合的优化,可以通过封装PreparedStatement的对SQL的操作处理来完成,在工具类中封装操作SQL的方法:

1 import java.sql.*;

2 import java.util.Objects;

3

4 /**

5 * @Description: JDBC工具类

6 * @author: snails

7 * @since: 2023/1/12 11:26

8 */

9 public class JdbcUtils {

10

11 private static final String URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8";

12 private static final String USERNAME = "root";

13 private static final String PASSWORD = "root";

14

15 public static Connection conn = null;

16 public static PreparedStatement ps = null;

17

18 /**

19 * 数据库连接

20 * @return

21 */

22 public static Connection getConnection() {

23 if (conn == null) {

24 try {

25 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);

26 } catch (SQLException e) {

27 e.printStackTrace();

28 }

29 }

30 return conn;

31 }

32

33 /**

34 * 关闭资源

35 * @param conn

36 * @param sta

37 * @param rs

38 */

39 public static void close(Connection conn, Statement sta, ResultSet rs) {

40 try {

41 // 关闭ResultSet

42 if (Objects.nonNull(rs)) {

43 rs.close();

44 }

45 // 关闭Statement

46 if (Objects.nonNull(sta)) {

47 sta.close();

48 }

49 // 关闭Connection

50 if (Objects.nonNull(conn)) {

51 sta.close();

52 }

53 } catch (SQLException e) {

54 e.printStackTrace();

55 }

56 }

57

58 /**

59 * 执行查询

60 * @param sql

61 * @param parameters

62 * @return

63 */

64 public static ResultSet executeQuery(String sql, Object...parameters) throws SQLException {

65 ResultSet rs = null;

66 // 获取数据库库连接

67 conn = getConnection();

68 // 创建Statement对象

69 ps = conn.prepareStatement(sql);

70 // 设置sql中的参数

71 if (Objects.nonNull(parameters) && parameters.length > 0) {

72 for (int i = 0; i < parameters.length; i++) {

73 ps.setObject(i+1, parameters[i]);

74 }

75 }

76

77 // 返回结果集

78 return ps.executeQuery();

79 }

80

81 }

查询逻辑的简化:

1 public void getUserInnfo() throws Exception {

2 // 查询

3 ResultSet rs = JdbcUtils.executeQuery("select * from user where id = ?", 101);

4 // 结果集的处理

5 while(rs.next()) {

6 System.out.println("用户名称:" + rs.getString("name"));

7 }

8 // 关闭资源

9 JdbcUtils.close(JdbcUtils.conn, JdbcUtils.ps, rs);

10 }

2.3、ResultSet结果集的优化

对于ResultSet结果集的优化,利用反射、元数据进行处理。

1 /**

2 * 数据库列与实体对象映射处理

3 * @param sql

4 * @param clazz

5 * @param parameters

6 * @param

7 * @return

8 * @throws Exception

9 */

10 public static List executeQuery(String sql, Class clazz, Object...parameters) throws Exception {

11 // 获取连接

12 conn = getConnection();

13 // 执行SQL获取结果集

14 ResultSet rs = executeQuery(sql, parameters);

15 // 获取表的元数据

16 ResultSetMetaData metaData = ps.getMetaData();

17

18 List resultList = new ArrayList<>();

19

20 // 结果集映射成对象实体

21 while(rs.next()) {

22 // 获取表字段总数

23 int columnCount = metaData.getColumnCount();

24 // 通过反射实例化对象

25 Object obj = clazz.newInstance();

26 // 遍历表字段

27 for (int i = 1; i <= columnCount; i++) {

28 // 列名

29 String columnName = metaData.getColumnName(i);

30 // 列值

31 Object columnValue = rs.getObject(i);

32 // 数据库字段与数据库值的映射

33 setFieldValueForColumn(obj, columnName, columnValue);

34 }

35 resultList.add((T) obj);

36 }

37 // 关闭资源

38 JdbcUtils.close(JdbcUtils.conn, JdbcUtils.ps, rs);

39

40 return resultList;

41 }

42

43 /**

44 * 根据字段名称设置对象属性

45 * @param o

46 * @param columnName

47 * @param columnValue

48 */

49 private static void setFieldValueForColumn(Object o, String columnName, Object columnValue) {

50 Class aClass = o.getClass();

51 try {

52 Field field = aClass.getDeclaredField(columnName);

53 field.setAccessible(true);

54 field.set(o, columnValue);

55 field.setAccessible(false);

56 } catch (Exception e) {

57 // 驼峰模式的处理

58 if (columnName.contains("_")) {

59 // \w -> 元字符,相当于 [a-zA-Z0-9]

60 Pattern pattern = Pattern.compile("_(\\w)");

61 columnName = columnName.toLowerCase();

62 Matcher matcher = pattern.matcher(columnName);

63 StringBuffer sb = new StringBuffer();

64

65 if (matcher.find()) {

66 // matcher.group(1) 指的是第一个括号里的东西 \w

67 // 替换掉_,并将_的相邻下一个字母转为大写

68 matcher.appendReplacement(sb, matcher.group(1).toUpperCase());

69 }

70 matcher.appendTail(sb);

71 // 再次调用复制操作

72 setFieldValueForColumn(o,sb.toString(),columnValue);

73 }

74 }

75 }

查询逻辑的简化:

1 public void getUserInnfo() throws Exception {

2 // 查询

3 List userList = JdbcUtils.executeQuery("select * from user where id = ?", User.class, 101);

4 // 结果集的处理

5 System.out.println("userList = " + userList);

6 }

通过上述的优化,我们只需要关注SQL的编写,大大提高了开发的效率。

正在为您跳转
苹果11英寸及以下笔记本电脑报价