JDBC---Java程序和数据库连接的桥梁
JDBC入门
What is JDBC?
全称:Java DataBase Connectivity
这里的数据库指的是关系型数据库,目前最常用的有:
oracle(用的最多的)、mysql(被Oracle收购的)、sqlserver(windows上用得最多的)、postgresql(和oracle相媲美的,并且还开源免费)、····
mysql以前是开源的,后来被sun公司收购,sun又被Oracle收购了,所以MySQL目前也是属于Oracle公司的。
MySQL被收购后,它的作者又开创了一个新的分支:MariaDB。所以MySQL和MariaDB是一奶同胞,师出同源的。
如果没有JDBC,Java程序想要访问mysql,就要写一套连接MySQL的程序,想要连接oracle,就要写一套连接oracle的程序,两种程序不能相互通信更不能相互替代,Java程序访问数据库就变得很不灵活:
有了JDBC之后,由JDBC为我们提供统一的访问数据库接口,我们的程序就变成了这样的:
在连接各种数据库时,java程序都按照JDBC的接口规范编写程序,写的程序都一样,唯独不同的是访问mysql套mysql的驱动,访问oracle套oracle的驱动,这样一来即可完成一套程序+各种数据库驱动 == 来访问各种数据库。
所以说JDBC是Java程序和标准数据库连接之间的桥梁。
但其实JDBC的程序写起来还是非常死的。
但它是Java程序操作数据库的基础。
先写第一个JDBC程序
JDBC有一个管理驱动的类:DriverManager。它用来统一管理各种数据库驱动。
要访问mysql数据库,所以我们需要先在maven工程下导入mysql驱动的类库:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
注意:驱动版本要对应mysql版本。
public static void main(String[] args) {
try{
Class.forName("com.mysql.jdbc.Driver");
}catch (ClassNotFoundException e){
e.printStackTrace();
}
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
String url = "jdbc:mysql://localhost/test?user=root&password=123456&serverTimezone=UTC";
conn = DriverManager.getConnection(url);
stmt = conn.createStatement();
String sql = "select * from book";
rs = stmt.executeQuery(sql);
while (rs.next()){
String bookid = rs.getString("bookid");
String bookname = rs.getString("bookname");
System.out.println(bookid+"--"+bookname);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(rs!=null)
rs.close();
if(stmt!=null)
stmt.close();
if(conn!=null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Class.forName("com.mysql.cj.jdbc.Driver");
得到的结果集的游标一开始在表的最上方,即处于一个空的位置,如果没有rs.next()就调用rs.getString(),会出现异常:
java.sql.SQLException:Before start of result set
使用Statement进行查询操作用的是executeQuery()方法,
增加、删除、修改操作使用它的executeUpdate()方法。
PreparedStatement
PreparedStatement可以灵活指定SQL语句中的变量,是一种特殊的statement。
写sql语句时变量以问号代替。
public static void main(String[] args) {
try{
Class.forName("com.mysql.jdbc.Driver");
}catch (ClassNotFoundException e){
e.printStackTrace();
}
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from book where book_num > ? and book_num < ?";
try {
String url = "jdbc:mysql://localhost/test?user=root&password=123456&serverTimezone=UTC";
conn = DriverManager.getConnection(url);
ps = conn.prepareStatement(sql);
ps.setInt(1,99);//索引从1开始的
ps.setInt(2,700);
rs = ps.executeQuery();
while (rs.next()){
String bookid = rs.getString("bookid");
String bookname = rs.getString("bookname");
System.out.println(bookid+"--"+bookname);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(rs!=null)
rs.close();
if(ps!=null)
ps.close();
if(conn!=null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
同样使用PreparedStatement 进行查询操作用的是executeQuery()方法,
增加、删除、修改操作使用它的executeUpdate()方法。
JDBC事务处理
事务(transaction):
- 一组操作,要么全完成,要么不完成,不取中间状态
- 目前大多数的数据库所提供的JDBC实现都提供原生事务支持
假如我们做一个转账操作,张三转给李四100块钱,我们需要两条sql语句,一条从张三的余额中扣除100块钱,一条从李四的余额中加上100。
每条sql语句的执行其实都是一个事务,如果该sql语句执行失败,那么它所做的操作会自动回滚。
但问题是假如我第一条sql语句执行成功了,第二条sql语句执行失败,这又该怎么办?
我们可以在JDBC程序中进行事务的处理:
- 事务开始前,设置Connection不自动提交
conn.setAutoCommit(false);
- 事务结束后,手动提交
conn.commit();
- 当捕获到异常,回滚事务
conn.rollback();
首先,我们根据这样一张表进行操作:
事务:张三向李四账户中转账100元。
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection conn = null;
Statement stmt = null;
String url = "jdbc:mysql://localhost/test?user=root&password=123456&serverTimezone=UTC";
try {
conn = DriverManager.getConnection(url);
stmt = conn.createStatement();
//事务开始
conn.setAutoCommit(false);
stmt.executeUpdate("update user_account set balance = 700 where username = '张三'");
stmt.executeUpdate("update user_account set balance = 900 where username = '李四'");
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}finally {
try {
if(conn!=null)
conn.close();
if(stmt!=null)
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}