个人博客网:https://wushaopei.github.io/ (你想要这里多有)
针对设问!相关问题如下:
1.什么是JDBC
2.怎么建立数据库连接(掌握)
3.关于Statement在操作数据表中的作用(了解)
4.使用PreparedStatement的 好处?具体应用方法是?(掌握)使用预编译的原因?连接数据库、操作表的步骤?
实现数据表的INSERT/UPDATE/DELETE操作
使用ResultSet和ResultSetMetaData实现数据表的SELECT操作
向数据表中插入、读取大数据:BLOB字段
INSERT / UPDATE / DELETE ; SELECT
6.数据库事务的操作方式(了解)
7.数据库连接池(理解)
C3P0数据库连接池
DBCP数据库连接池
8.JDBUtils工具类的使用(掌握)
使用QueryRunner,实现UPDATE()和QUERY()方法
利用DbUtils编写DAO通用类
解:
·1.1基础:
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API);JDBC可以连接任何提供了JDBC驱动程序的数据库系统;
·1.2 JDBC体系结构:
JDBC接口(API)包括两个层次:
面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。
JDBC是sun公司提供一套用于数据库操作的接口,java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。————面向接口编程
API执行流程图:
·2 获取数据库的连接
- 实现数据库连接的前提:a.加载与注册JDBC驱动;b.数据库 url;c.user 、password
- Driver接口:
Oracle的驱动:oracle.jdbc.driver.OracleDriver
mySql的驱动: com.mysql.jdbc.Driver
a. 加载与注册JDBC驱动分为两种方式:
方式一:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动名的类Class.forName(“com.mysql.jdbc.Driver”);
方式二:DriverManager 类是驱动程序管理器类,负责管理驱动程序
DriverManager.registerDriver(com.mysql.jdbc.Driver);
通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例
b.url的标准构成及对应数据库的使用形式:
·对于 Oracle 数据库连接,采用如下形式:
jdbc:oracle:thin:@localhost:1521:atguigu
·对于 SQLServer 数据库连接,采用如下形式:
jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid
·对于 MYSQL 数据库连接,采用如下形式:
jdbc:mysql://localhost:3306/atguigu
c. User,password可以用“属性名=属性值”方式告诉数据库;
·2.2 建立连接(Connection)
分为两类共5中方式:
A类:使用驱动Driver对象建立连接
a.连接方式一: 创建驱动对象driver,与数据源地址url和账号、密码进行校验、连接--配置文件对象
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
41a.连接方式一: 创建驱动对象driver,与数据源地址url和账号、密码进行校验、连接--配置文件对象 @Test public void test() throws Exception { //1.获取驱动 Driver driver = new com.mysql.jdbc.Driver(); //2.数据库连接的url String url = "jdbc:mysql://localhost:3306/test"; //3.用配置流设置数据库的账户和密码 Properties info = new Properties(); info.setProperty("user", "root"); info.setProperty("password", "root"); //4.连接数据库 Connection connection = driver.connect(url,info); System.out.println(connection); } b.连接方式二:通过反射获取驱动Driver对象driver(要向下转型)--配置文件对象 /* * 连接方式二:通过反射获取驱动Driver对象driver(要向下转型)--配置文件对象 * 体会面向接口的编程思想 */ @Test public void test2() throws Exception { //1.用驱动的全类名获取运行时类,创建Object类对象,获取驱动对象 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Object object = clazz.newInstance(); Driver driver = (Driver)object; //2.创建url链接 String url = "jdbc:mysql://localhost:3306/test"; //3.创建配置文件设置登陆账户与密码 Properties info = new Properties(); info.getProperty("user","root"); info.getProperty("password","root"); //4.链接数据库 Connection connection = driver.connect(url,info); System.out.println(connection); }
B类:使用DriverMananger两个操作
* 1.注册驱动
* 2.获取连接
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
71c.连接方式三:通过DriverMananger获取数据库的连接 @Test public void test3() throws Exception { //1.创建运行时类,获取驱动对象 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Object object = clazz.newInstance(); Driver driver =(Driver)object; //2.创建url数据源 String url ="jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "root"; //3.注册驱动 DriverManager.registerDriver(driver); //4.通过注册器 链接数据库 Connection connection = DriverManager.getConnection(url, user,password); System.out.println(connection); } d.连接方式四:mysql驱动默认会进行驱动的注册 @Test public void test4() throws Exception { //1.创建驱动的运行时类 Class clazz =Class.forName("com.mysql.jdbc.Driver"); //2.创建数据库账号、密码、url2.创建数据库账号、密码、url源源 String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "root"; /* * mysql可以不用注册,其它的数据库必须进行注册 * 这一步不要省。 */ //链接数据库 Connection connection =DriverManager.getConnection(url,user,password); System.out.println(connection); } e.方式五:使用配置文件获取数据库的连接(配置文件中存放user、password、url、driver) @Test public void test5() throws Exception { //1.从配置文件读取数据 InputStream iStream = this.getClass().getClassLoader() .getResourceAsStream("sqlDriver.properties"); //2.创建配置文件对象 Properties ps = new Properties(); //3.加载文件内容到配置文件对象中 ps.load(iStream); //3.从配置文件对象获取账户、密码、url、driver String user= ps.getProperty("user"); String password = ps.getProperty("password"); String driverClass = ps.getProperty("driverClass"); String url = ps.getProperty("url"); //4.创建驱动对象 Class clazz =Class.forName(driverClass); Object object = clazz.newInstance(); Driver driver = (Driver)object; //5.注册驱动 DriverManager.registerDriver(driver); //6.链接驱动 Connection connection = DriverManager.getConnection(url,user,password); System.out.println(connection); } }
·3.Statement 接口的使用与弊端
a.在对数据库的数据进行增删改查之前要先进行预编译,也就是对数据进行调用,java.sql 包中有 3 个接口:Statement、 PrepredStatement、CallableStatement.
b.Statement会遭受SQL注入攻击,所以不建议使用,主要使用PreparedStatement(从Statement扩展而来)
SQL注入攻击:利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,从而利用系统的 SQL 引擎完成恶意行为的做法
·4.1.PreparedStatement 的好处,及应用方法
好处:最大可能提高性能(DBServer会对预编译语句提供性能优化)、最大可能提高性能
预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。(重要)
连接数据库、操作表的步骤
释放资源:ResultSet 、 Connection PerpareStatement
关于ResultSet的说明
ResultSet: 结果集. 封装了使用 JDBC 进行查询的结果.
调用 PreparedStatement 对象的 executeQuery() 可以得到结果集.
ResultSet 返回的实际上就是一张数据表. 有一个指针指向数据表的第一条记录的前面.
相当于Iterator 对象的 hasNext() 和 next() 方法的结合体
当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值.
例如: getInt(1), getString("name")
获取ResultSet中结果集的API常用方法:
next() 方法移动到下一行
getString() 根据占位符可获取对应的字符串数据
getInt().....套用以上格式
·4.2.ResultSetMetaData 类:
从结果集获取表结构(元数据):
ResultSetMetaData meta = rs.getMetaData();
元数据常用API:
getColumnName(int column):获取指定列的
名称
getColumnLabel(int column):获取指定列的别名
getColumnCount():返回当前 ResultSet 对象中的列数。
getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
得到结果集后, 如何知道该结果集中有哪些列 ? 列名是什么 ---- 需要使用一个描述 ResultSet 的对象, 即 ResultSetMetaData
ResultSetMetaData:可以获取对应的 ResultSet 有多少列, 每一列的列名都是什么。
1.如何获取 ResultSetMetaData: 调用 ResultSet 的 getMetaData() 方法即可
2.获取 ResultSet 中有多少列:调用 ResultSetMetaData 的 getColumnCount() 方法
3.获取 ResultSet 每一列的列的别名是什么。getColumnLabel() 方法
·4.3实现数据表的INSERT/UPDATE/DELETE操作
封装连接数据库到方法中——JDBCUtils
·4.3.1 普通增删改
1.封装连接数据库到方法中
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100/* * 通用的增删改 */ public static int UID(String sql,Object ...objects) { //1.获取数据库的链接 Connection connection=null; //2.预编译 PreparedStatement ps=null; //4.执行sql语句 int executeUpdate=-1; try { connection = JDBCUtils.getConnection(); ps = connection.prepareStatement(sql); //3.填充数据 for (int i = 0; i < objects.length; i++) {// i 表示索引 ps.setObject(i + 1, objects[i]);// i + 1表示的是第几个占位符 } executeUpdate = ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { //5.关闭资源 JDBCUtils.close(connection, ps); } return executeUpdate; } /* * 获取数据库的连接 */ public static Connection getConnection() { // 数据库的连接 Connection connection = null; InputStream is = null; try { is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties"); Properties ps = new Properties(); ps.load(is); String user = ps.getProperty("user"); String password = ps.getProperty("password"); String driverClass = ps.getProperty("driverClass"); String url = ps.getProperty("url"); // 创建Driver对象 Class clazz = Class.forName(driverClass); Object obj = clazz.newInstance(); Driver driver = (Driver) obj; // 注册驱动 DriverManager.registerDriver(driver); connection = DriverManager.getConnection(url, user, password); } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return connection; } public static void close(Connection connection,PreparedStatement ps) { if(connection!=null) { try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(ps!=null) { try { ps.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void close(Connection connection,PreparedStatement ps,ResultSet rs) { close(connection, ps); if(rs !=null ) { try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
2.调用连接数据库类,填充数据,执行,关闭资源(关源封装到方法中
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210public class CRUDTest { /* * 向数据库中插入一条数据 */ @Test public void insert() { //1.链接数据库 Connection connection=null; //3.预编译 PreparedStatement ps=null; try { connection = JDBCUtils.getConnection(); //2.创建SQL语句 String sql = "INSERT INTO customers(NAME,EMAIL,birth)" + " VALUES(?,?,?);"; ps = connection.prepareStatement(sql); //4.设置内容 ps.setString(1, "少培");// 第一个参数:第几个问号 第二个参数:内容 ps.setString(2, "shaopei@qq.com"); Date date = new Date(new java.util.Date().getTime());// 获取一个sql下的Date ps.setDate(3, date); //5.执行sql语句 ps.execute(); } catch (Exception e) { // TODO: handle exception }finally { //6.关闭资源 JDBCUtils.close(connection,ps); } } /* * 删除一条件数 */ @Test public void delete() { //1.获取数据库的链接 Connection connection=null; //3.预编译 PreparedStatement ps=null; try { connection = JDBCUtils.getConnection(); //2.创建sql语句 String sql = "DELETE FROM customers WHERE id = ?"; ps = connection.prepareStatement(sql); //4.填充数据 ps.setInt(1, 19); //5.执行sql语句 int i = ps.executeUpdate(); System.out.println(i + "条语句受到影响"); } catch (Exception e) { // TODO: handle exception } //6.关闭资源 JDBCUtils.close(connection, ps); } /* * 修改一条件数 */ @Test public void update () throws Exception { //1.获取数据库的链接 Connection connection=null; //3.预编译 PreparedStatement ps=null; try { connection = JDBCUtils.getConnection(); //2.创建sql语句 String sql = "UPDATE customers SET NAME = ? WHERE id =?"; ps = connection.prepareStatement(sql); //4.填充数据 ps.setString(1, "霍光"); ps.setInt(2, 21); //5.执行sql语句 int executeUpdate = ps.executeUpdate(); } catch (Exception e) { // TODO: handle exception }finally { //6.关闭资源 JDBCUtils.close(connection,ps); } } } 2.通用增删改 1.封装连接数据库到方法中,执行语句也封装到同一个类中的方法中 /* * 通用的增删改 */ public static int UID(String sql,Object ...objects) { //1.获取数据库的链接 Connection connection=null; //2.预编译 PreparedStatement ps=null; //4.执行sql语句 int executeUpdate=-1; try { connection = JDBCUtils.getConnection(); ps = connection.prepareStatement(sql); //3.填充数据 for (int i = 0; i < objects.length; i++) {// i 表示索引 ps.setObject(i + 1, objects[i]);// i + 1表示的是第几个占位符 } executeUpdate = ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { //5.关闭资源 JDBCUtils.close(connection, ps); } return executeUpdate; } /* * 获取数据库的连接 */ public static Connection getConnection() { // 数据库的连接 Connection connection = null; InputStream is = null; try { is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties"); Properties ps = new Properties(); ps.load(is); String user = ps.getProperty("user"); String password = ps.getProperty("password"); String driverClass = ps.getProperty("driverClass"); String url = ps.getProperty("url"); // 创建Driver对象 Class clazz = Class.forName(driverClass); Object obj = clazz.newInstance(); Driver driver = (Driver) obj; // 注册驱动 DriverManager.registerDriver(driver); connection = DriverManager.getConnection(url, user, password); } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return connection; } public static void close(Connection connection,PreparedStatement ps) { if(connection!=null) { try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(ps!=null) { try { ps.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void close(Connection connection,PreparedStatement ps,ResultSet rs) { close(connection, ps); if(rs !=null ) { try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } 2.创建sql语句及Date数据,调用连接数据库方法并调用执行方法。 public class CRUDTest2 { /* * 测试通用的增删改 */ @Test public void insert() { //1.创建sql语句 String sql = " INSERT INTO customers(NAME,email,birth) VALUES(?,?,?)"; //2.获取日期数据 Date date =new java.sql.Date(new java.util.Date().getTime()); //3.调用通用方法,执行修改 int uid = JDBCUtils.UID(sql, "王玄策","wangxuance@qq.com",date); //4.返回结果int System.out.println(uid + "条语句收到影响"); } }
·4.3.2
数据库的查找
1.普通查找
从数据库中查找一条数据或多条数据
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157从数据库中查找一条数据或多条数据 public class CRUDTest3 { /* * 从数据库中查找一条数据或多条数据 */ @Test public void select() throws Exception { Customer customer = getCustomerById(); System.out.println(customer); List <Customer> list = getCustomers(); for (Customer customer2 : list) { System.out.println(customer2); } } /* * 查询多条数据 */ public List<Customer>getCustomers() throws Exception { //1.创建数据库连接 Connection connection = JDBCUtils.getConnection(); //2.创建sql语句 String sql = "select * from customers"; //3.预编译 PreparedStatement ps = connection.prepareStatement(sql); //4.执行sql语句 ResultSet rs = ps.executeQuery(); //5.创建用于保存数据的集合 List<Customer> list = new ArrayList<>(); //6.获取数据,并将其封装的集合中 while(rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); String email = rs.getString("email"); Date date = rs.getDate("birth"); Customer customer = new Customer(id,name,email,date); list.add(customer); } //7.关闭资源 JDBCUtils.close(connection,ps,rs); return list; } /* * 查询一条数据 */ public Customer getCustomerById() throws Exception { //1.获取数据库的连接 Connection connection = JDBCUtils.getConnection(); //2.创建sql语句 String sql = "SELECT * FROM customers where id =?"; //3.预编译 PreparedStatement ps = connection.prepareStatement(sql); //4.填充数据 ps.setInt(1, 20); //5.执行sql语句 ResultSet rs = ps.executeQuery();// 查找的结果都已经放到ResultSet中了 Customer customer=null; //6.从结果集中获取数据 if(rs.next()) { int id =rs.getInt("id"); String name = rs.getString("name"); String email = rs.getString("email"); Date birth = rs.getDate("birth"); //7.封装数据到自定义类中 customer= new Customer(id,name,email,birth); //8.输出结果 System.out.println(id + " " +name + " "+ email + " " +birth); } JDBCUtils.close(connection, ps,rs); return customer; } } /* * 获取数据库的连接 */ public static Connection getConnection() { // 数据库的连接 Connection connection = null; InputStream is = null; try { is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties"); Properties ps = new Properties(); ps.load(is); String user = ps.getProperty("user"); String password = ps.getProperty("password"); String driverClass = ps.getProperty("driverClass"); String url = ps.getProperty("url"); // 创建Driver对象 Class clazz = Class.forName(driverClass); Object obj = clazz.newInstance(); Driver driver = (Driver) obj; // 注册驱动 DriverManager.registerDriver(driver); connection = DriverManager.getConnection(url, user, password); } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return connection; } public static void close(Connection connection,PreparedStatement ps) { if(connection!=null) { try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(ps!=null) { try { ps.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void close(Connection connection,PreparedStatement ps,ResultSet rs) { close(connection, ps); if(rs !=null ) { try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
2.通用查找
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129public class JDBCUtils2 { public static void main(String[] args) throws Exception { //创建sql语句 String sql = "select id,name,email,birth from customers where id=?"; Customer customer = getObject(Customer.class, sql, 5); System.out.println(customer); sql = "select * from users where id=?"; User object = getObject(User.class, sql, 1); System.out.println(object); sql = "select * from users"; List <User> users = getObjects(User.class, sql); for (User user : users) { System.out.println(user); } } /* * 通用的查找 (只一条数据) * * Class<T> clazz : 运行时类的对象 */ public static <T> T getObject(Class<T>clazz,String sql,Object ...objects) throws Exception { //1.获取数据库的连接 Connection connection =JDBCUtils.getConnection(); //2.预编译 PreparedStatement ps = connection.prepareStatement(sql); //3.填充数据 for(int i = 0;i<objects.length;i++) { ps.setObject(i+1, objects[i]); } //4.执行sql语句 ResultSet rs = ps.executeQuery(); //5.获取元数据 ResultSetMetaData md = rs.getMetaData(); //6.获取列的数量 int columnCount = md.getColumnCount(); //7.创建运行时类的对象 T t =clazz.newInstance(); //8.while循环获取每一条数据 while(rs.next()) {//遍历每一条数据 /* * 第一个问题 : 如何获取到表的列数 * 第二个问题 : 需要知道类中的属性 * 第个问题 : 对象中属性的名字怎么来 */ //9.for循环获取每一列的数据并封装到自定义对象的属性中 for(int i =0;i<columnCount;i++) { //a.通过列的索引获取列明(如果别名获取的是别名 String columnLabel=md.getColumnLabel(columnCount); //b.通过列名获取列中的数据 Object value = rs.getObject(columnLabel); //封装 //通过反射 - 给对象中的属性进行赋值 //将表中的列名当作类中的属性名。如果列名和属性名不一样,可以通过别名的方式(别名 = 属性名 //通过列名就获取到了类中的对应的属性 Field declaredField = clazz.getDeclaredField(columnLabel); declaredField.setAccessible(true); /* * 第一个参数 : 是给哪个对象进行赋值 * 第二个参数 : 属性值 */ declaredField.set(t,value); } } //关闭资源 JDBCUtils.close(connection,ps,rs); return t; } /* * 通用的查找 (返回多条数据 * */ public static <T> List<T> getObjects(Class<T>clazz,String sql,Object...objects) throws Exception{ //1.获取数据库的连接 Connection connection = JDBCUtils.getConnection(); //2.预编译 PreparedStatement ps = connection.prepareStatement(sql); //3.填充数据 for(int i= 0;i<objects.length;i++) { ps.setObject(i+1, objects[i]); } //4.执行sql语句 ResultSet rs = ps.executeQuery(); //5.获取元数据 ResultSetMetaData md = rs.getMetaData(); //6.获取列数 int colunmCount = md.getColumnCount(); //7.创建一个集合用于接收数据 List <T> list = new ArrayList<>(); //8.while循环获取每一条数据 while(rs.next()) { //a.创建对象 T t = clazz.newInstance(); //b.获取每一列的列名,并且通过列明获取数据 for(int i=0;i<colunmCount;i++) { //获取列名 String columnLabel = md.getColumnLabel(i+1); //获取列的数据 Object value = rs.getObject(columnLabel); //封装 //通过反射 - 给对象中的属性进行赋值 //将表中的列名当作类中的属性名。如果列名和属性名不一样,可以通过别名的方式(别名 = 属性名 //通过列名就获取到了类中的对应的属性 Field declardField = clazz.getDeclaredField(columnLabel); declardField.setAccessible(true); /* * 第一个参数 : 是给哪个对象进行赋值 * 第二个参数 : 属性值 */ declardField.set(t, value); } //将对象放入集合中 list.add(t); } //关闭资源 JDBCUtils.close(connection, ps,rs); return list; } }
·4.3.3 向数据表中插入、读取大数据:BLOB字段
MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
BLOB字段由两部分组成:数据(值)和指向数据的指针(定位器)。定位器被存放在列中,值被存放在LOB段中,LOB段是在数据库内部表的一部分。在写入Blob之前,必须获得指针(定位器)才能进行写入.
如何获得Blob的指针(定位器) :需要先插入一个empty的blob,这将创建一个blob的指针,然后再把这个empty的blob的指针查询出来,这样通过两步操作,就获得了blob的指针,可以真正的写入blob数据了
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/* * 获取Blob类型的数据 * * 向Blob字段中插入数据 */ public class BlobTest { @Test public void insert() throws Exception{ Connection connection = JDBCUtils.getConnection(); String sql = "insert into customers(photo) values(?)"; PreparedStatement ps = connection.prepareStatement(sql); FileInputStream fis = new FileInputStream("123.jpg"); ps.setBlob(1, fis); boolean execute = ps.execute(); fis.close(); //关流 JDBCUtils.close(connection, ps); } // /* 从数据库读取数据,写到目录下 */ @Test public void select() throws Exception{ Connection connection = JDBCUtils.getConnection(); String sql = "select photo from customers where id = ?"; PreparedStatement ps = connection.prepareStatement(sql); ps.setInt(8, 21); ResultSet rs = ps.executeQuery(); if(rs.next()){ Blob blob = rs.getBlob("photo"); InputStream is = blob.getBinaryStream(); FileOutputStream fos = new FileOutputStream("555.jpg"); byte[] b = new byte[1024]; int len = 0; while((len = is.read(b)) != -1){ fos.write(b,0,len); } fos.close(); is.close(); } JDBCUtils.close(connection, ps,rs); } }
·4.4 数据库事务
1.事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。
2.事务处理(事务操作):保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态
3.为了让多个 SQL 语句作为一个事务执行:
调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
在出现异常时,调用 rollback(); 方法回滚事务
若此时 Connection 没有被关闭, 则需要恢复其自动提交状态
4.事务的ACID(acid)属性
a. 原子性
b. 一致性
c. 隔离性
d. 持久性、
代码:
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187package com.atguigu.java2; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.junit.Test; import com.atguigu.java.JDBCUtils; /* * 数据库事务 */ public class Transaction { /* * 需求 : AA 给 BB 转账 * 第一步:AA减去100 * 第二步 :BB加上100 * * UPDATE user_table SET balance=balance - 100 WHERE USER='AA' UPDATE user_table SET balance=balance + 100 WHERE USER='BB' * * 要完成都完成,要失败都失败。 * * 注意 :1.事务中多个sql语句必须使用同一个连接。 */ @Test public void test(){ String sql = " UPDATE user_table SET balance=? WHERE USER=?"; Connection connection = JDBCUtils.getConnection(); try { //设置不让自动提交 connection.setAutoCommit(false); UID(connection,sql, 900, "AA"); System.out.println(1 / 0); UID(connection,sql, 1100, "BB"); connection.commit(); } catch (Exception e) { //回滚 try { connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } }finally{ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } /* * 通用的增删改 */ public int UID(Connection connection,String sql,Object ...objects) { // 2. 预编译 PreparedStatement ps = null; // 4.执行sql语句 int executeUpdate = -1; try { ps = connection.prepareStatement(sql); // 3.填充数据 for (int i = 0; i < objects.length; i++) { // i 表示索引 ps.setObject(i + 1, objects[i]); // i + 1表示的是第几个占位符 } executeUpdate = ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } return executeUpdate; } } 工具类: package com.atguigu.java; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; public class JDBCUtils { /* * 通用的增删改 */ public static int UID(String sql,Object ...objects) { // 1. 获取数据库的连接 Connection connection = null; // 2. 预编译 PreparedStatement ps = null; // 4.执行sql语句 int executeUpdate = -1; try { connection = JDBCUtils.getConnection(); ps = connection.prepareStatement(sql); // 3.填充数据 for (int i = 0; i < objects.length; i++) { // i 表示索引 ps.setObject(i + 1, objects[i]); // i + 1表示的是第几个占位符 } executeUpdate = ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally{ // 5.关闭资源 JDBCUtils.close(connection, ps); } return executeUpdate; } /* * 获取数据库的连接 */ public static Connection getConnection() { // 数据库的连接 Connection connection = null; InputStream is = null; try { is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties"); Properties ps = new Properties(); ps.load(is); String user = ps.getProperty("user"); String password = ps.getProperty("password"); String driverClass = ps.getProperty("driverClass"); String url = ps.getProperty("url"); // 创建Driver对象 Class clazz = Class.forName(driverClass); Object obj = clazz.newInstance(); Driver driver = (Driver) obj; // 注册驱动 DriverManager.registerDriver(driver); connection = DriverManager.getConnection(url, user, password); } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return connection; } public static void close(Connection connection, PreparedStatement ps) { if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Connection connection, PreparedStatement ps, ResultSet rs) { close(connection,ps); if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
最后
以上就是天真鼠标最近收集整理的关于JDBC连接数据原理与事务的全部内容,更多相关JDBC连接数据原理与事务内容请搜索靠谱客的其他文章。
发表评论 取消回复