avatar

目录
JDBC增删改查的封装-mysql

本篇博客内容:

  • JDBC操作的简单封装。

1 数据库(mysql)操作

在数据库中创建一张表,这里以用户表为例,如下图:table_name:user,您的table,怎么舒服怎么建:
还有jdbc驱动的jar包的引入我就略了,不要忘记导入这个jar包噢
user

2 创建类(User.java)

先封装一个用户类(User),当然你可以封装其他的类,在封装类的时候注意以下两点:

1. 类中的属性名要和数据库对应表的列名一致(一模一样拿过来就对了):是为了方便后面通过内省获取指定方法,名字不一样的话,找到地老天荒也找不到┗|`O′|┛ 嗷~~
2. 属性(成员)的数据类型最好是包装类型:通过内省获取的方法传参时用的是从数据库中拿出来的数据(放到结果集中了),你可以测试一下,这些数据是包装类型欧
也可以不实现Serializable接口,这个是实现数据库连接池时使用的,懒得删了~

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.myproject.beans;
import java.io.Serializable;
/**
* Administrator
* 2019/4/15 0015
* 用户类
*/
public class User implements Serializable {
private static final long serialVersionUID = 373910607014836778L;
private Integer id;
private String username;
private String password;
private Integer age;
private String gendar;

public User() {
}

public User(Integer id, String username, String password, Integer age, String gendar) {
this.id = id;
this.username = username;
this.password = password;
this.age = age;
this.gendar = gendar;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public String getGendar() {
return gendar;
}

public void setGendar(String gendar) {
this.gendar = gendar;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
", gendar='" + gendar + '\'' +
'}';
}
}

3 创建配置文件(db.properties)

主要是将连接数据库的几个变量封装一下,更换数据库信息的时候,我们只需要修改这个配置文件中的内容即可,对,一切为了方便,emm~懒创造了高效的代码:

Code
1
2
3
4
5
6
7
8
9
#驱动名称
driverClass=com.mysql.jdbc.Driver
#数据库url
url=jdbc:mysql:///mydatebase
#当然上面的这句话就等价于:url=jdbc:mysql://localhost:3306/mydatabase
#数据库用户名
user=root
#数据库密码
password=root

4 创建封装类(DB_Tools.java)

本篇博客所有的精华都在这里了,来让我们一起来感受一下:

4.1 注册JDBC驱动

将注册驱动的实现代码置于静态代码块中,类被调用时首先被加载:
通过加载配置文件,完成JDBC的驱动注册,(悄咪咪的问一下,看到这里的你应该知道不同的数据库有不同的JDBC驱动不~

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class DB_Tools{
private static String driverClass;
private static String url;
private static String user;
private static String password;
/**
*1.注册JDBC驱动
*/
static {
try {
//获取配置文件
InputStream inputStream = DB_Tools.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(inputStream);
//从配置文件中获取数据信息
driverClass = properties.getProperty("driverClass");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
try {
//注册驱动
Class.forName(driverClass);
System.out.println("注册驱动成功");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("注册驱动失败");
}
}
}

4.2 获取数据库连接

这个感觉没有什么好说的,就是常规操作嘛~

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class DB_Tools{
/**
* 2.获取连接
* @return Connection null连接失败 !null连接成功
*/
public static Connection getDBConnection() {
try {
return DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}

4.3 断开连接释放资源

emmm,这个也是常规操作~
注意以下关闭的顺序就好了,这里我们用PreparedStatement的父类Statement(虽然我不是很喜欢这个接口),使代码更加灵活.

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class DB_Tools{
/**
* 3.释放资源close()
* @param connection 连接
* @param preparedStatement 执行命令
* @param resultSet 结果集
*/
public static void allClose(Connection connection, Statement statement, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement!= null) {
statement.close();
}
if (connection != null) {
connection.close();
}
System.out.println("执行结束");
} catch (SQLException e) {
e.printStackTrace();
}
}
}

4.4 执行增删改查

代码中都有注释,我是仙女本仙没错了~看看下面的代码,增删改的操作返回的结果是一个int类型的数字:
操作成功 结果>0 返回受影响的行数,
操作失败 结果<0 返回的是一个负数,
还有一个点:这里用PreparedStatement,本仙不喜欢Statement,Statement会发生sql注入,嫌弃.PreparedStatement相对来说会做预处理,执行效率高还比较安全,可以举一个生动形象的例子:Statement是我眼里的渣男,而PreparedStatement就是那完美的男神!
代码如下:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class DB_Tools{
/**
* 4.执行增删改
* @param sql sql操作语句
* @param objects sql语句中的参数,可以为null
* @return int >0操作(增删改)成功 <0操作失败
*/
public static int excumentDBUpdate(String sql, Object[] objects) {
int updateResult = 0;
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
//1.获取连接
connection = getDBConnection();
//2.获取增删改查的执行命令
preparedStatement = connection.prepareStatement(sql);
//3.向sql语句中?填充数据
if (objects != null) {
for (int i = 0; i < objects.length; i++) {
preparedStatement.setObject(i + 1, objects[i]);
}
}
//4.执行增删改查
updateResult = preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.关闭连接,释放资源
allClose(connection, preparedStatement, null);
}
return updateResult;
}
}

4.5 (重点)查询数据

你也能看出来,前面的都太简单了,嗯哼不用写出来,谁都会的么那重点就来了:
下面的炫点有三个:

1.泛型的使用
2.反射的使用
> 3.内省的使用
上面使代码复用性更高

4.5.1 查询单条数据

思路:如代码中注释所示(我是有个仙女没错了,写代码还加注释~)

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public class DB_Tools{
//这个我先放在前面,后面就不再赘述了
/**
* 通过反射+内省将结果集中数据拿出来
* @param resultSet 结果集啊
* @param tClass 传递过来的操作类
* @param 泛型
* @return 返回一个泛型对象Object
* @throws Exception
*/
public static T getObject(ResultSet resultSet, Class tClass) throws Exception {
T object = tClass.newInstance();
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) {
//获取列名
String colName = resultSetMetaData.getColumnName(i + 1);
//通过内省获取包含列名指定方法(一般是get和set)
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(colName, tClass);
if (propertyDescriptor != null) {
//获取到方法后我们再获取set方法来对private修饰的相关属性进行赋值
Method method = propertyDescriptor.getWriteMethod();
//然后我们执行这个方法并将属性添加到object对象中
method.invoke(object, resultSet.getObject(colName));
}
}
return object;
}

/**
* 5.查询单条数据(反射加内省实现)
*
* @param sql sql操作语句
* @param objects sql语句中的参数,可以为null
* @param tClass
* @param 泛型
* @return 返回单个实体对象
*/
public static T getSingleResult(String sql, Object[] objects, Class tClass) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
T object = null;

try {
//1.获取连接
connection = getDBConnection();
//2.创建命令对象
preparedStatement = connection.prepareStatement(sql);
//3.向sql语句中添加数据(objects),如果objects不为空的话
if (objects != null) {
for (int i = 0; i < objects.length; i++) {
preparedStatement.setObject(i + 1, objects[i]);
}
}
//4.执行查询语句
resultSet = preparedStatement.executeQuery();
//5.通过反射创建tClass类的对象
//6.从结果集中获取数据
if (resultSet.next()) {
object = getObject(resultSet, tClass);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//7.关闭连接释放资源
allClose(connection, preparedStatement, resultSet);
}
//8.返回object对象
return object;
}
}

4.5.2 查询多条数据

实现和前面的思路如出一辙,我们这里有个人的脚超级臭(我发现好像是我胖胖的同桌的jio…..),伴着阵阵吹向我的方向的微风,我快给熏牺牲了,怀疑人生….快速沾完这个代码撤!狗命重要!

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class DB_Tools{
/**
* 5.2查询多条数据(反射+内省实现)
*
* @param sql sql操作语句
* @param objects sql语句中的参数,可以为null
* @param tClass
* @param 泛型
* @return 返回多个对象的集合
*/
public static List getComplexResult(String sql, Object[] objects, Class tClass) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
List tList = new ArrayList();

try {
//1.获取连接
connection = getDBConnection();
//2.创建命令对象
preparedStatement = connection.prepareStatement(sql);
//3.向sql语句中添加数据(objects),如果objects不为空的话
if (objects != null) {
for (int i = 0; i < objects.length; i++) {
preparedStatement.setObject(i + 1, objects[i]);
}
}
//4.执行查询语句
resultSet = preparedStatement.executeQuery();
//5.从结果集中获取数据
while (resultSet.next()) {
T object = getObject(resultSet, tClass);
tList.add(object);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//7.关闭连接释放资源
allClose(connection, preparedStatement, resultSet);
}
//8.返回tList集合
return tList;
}
}

本篇博客只是模拟了对JDBC增删改查超简易封装,和Apache提供的对JDBC进行简单封装的开源工具类库DBUtils还相差甚远,后面有时间我会写一篇关于DBUtils这个轻量级工具类的介绍,敬请期待.

感谢你看到了这里啊,
如果你有收获的话记得点赞呦
有问题可以留言,本仙看见了就会回复的
再见,祝您学习快乐,生活愉快~

文章作者: XiaoMing
文章链接: https://xiaoming0929.github.io/2020/04/02/JDBC%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5%E5%B0%81%E8%A3%85-mysql/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 XiaoMing's Blog
打赏
  • 微信
    微信
  • 支付寶
    支付寶