JDBC的概念
JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
JDBC的使用流程
导入jar包
1、下载有关数据库的jar包(下载地址:http://central.maven.org/maven2/mysql/mysql-connector-java/)
2、导入jar包,在Build Path里配置环境
Build Path-->Add JARs
加载驱动
// 加载驱动程序:Class.forName(driverClass)
// 加载mysql驱动:
Class.forName("com.mysql.jdbc.Driver");
Class.forName("com.mysql.cj.jdbc.Driver"); // 8.0版本以后的mysql驱动
// 加载oracle驱动:
Class.forName("oracle.jdbc.driver.OracleDriver");
获取数据库连接对象
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, user, password);
参数含义:
url: 表示要连接的数据地址
user: 数据库的用户名
password: 数据库的密码
作用:
连接到指定的数据库并返回连接对象。
创建sql命令对象(编译和发送sql命令给数据库)
Statement stmt = conn.createStatement();
创建sql命令
String sql = "insert into user values(13,'王13','wang13')";
指定sql命令,获得返回结果
int i = stmt.executeUpdate(sql);
ResultSet rs = stmt.executeQuery(sql)
增删改 时调用 stmt.executeUpdate(sql)方法。返回值为 int类型。大于等于 1 时表示成功,为 0 时表示失败。
查询 调用 stmt.executeQuery(sql)方法。返回ResultSet 类型,表示一个结果集。
ResultSet对象是基于指针进行数据存储的,类似枚举。不便于数据的针对性的获取。可将数据转换到ArrayList中进行存储。
关闭资源
stmt.close();
conn.close();
关闭之前打开的资源。需要抛出异常。
对数据的增删改查
增加 (insert)
// 声明jdbc变量
Connection conn = null;
Statement stmt = null;
// 声明jdbc参数
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123456";
try {
// 1 加载驱动类
Class.forName(driver);
// 2.获取数据库连接对象(连接指定数据库)
conn = DriverManager.getConnection(url, user, password);
// 3.创建sql命令对象(编译和发送sql命令给数据库)
stmt = conn.createStatement();
// 4.创建sql命令
String sql = "insert into user values(13,'王13','wang13')";
// 5.指定sql命令
int i = stmt.executeUpdate(sql);
System.out.println("执行结果:" + i);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 6.关闭资源
try {
stmt.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
修改 (update)
// 声明jdbc变量
Connection conn = null;
Statement stmt = null;
// 声明jdbc参数
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123456";
try {
// 1 加载驱动类
Class.forName(driver);
// 2.获取数据库连接对象(连接指定数据库)
conn = DriverManager.getConnection(url, user, password);
// 3.创建sql命令对象(编译和发送sql命令给数据库)
stmt = conn.createStatement();
// 4.创建sql命令
String sql = "update user set username='王update' where id=13";
// 5.指定sql命令
int i = stmt.executeUpdate(sql);
System.out.println("执行结果:" + i);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 6.关闭资源
try {
stmt.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
删除 (delete)
// 声明jdbc变量
Connection conn = null;
Statement stmt = null;
// 声明jdbc参数
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123456";
try {
// 1 加载驱动类
Class.forName(driver);
// 2.获取数据库连接对象(连接指定数据库)
conn = DriverManager.getConnection(url, user, password);
// 3.创建sql命令对象(编译和发送sql命令给数据库)
stmt = conn.createStatement();
// 4.创建sql命令
String sql = "delete from user where id=11";
// 5.指定sql命令
int i = stmt.executeUpdate(sql);
System.out.println("执行结果:" + i);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 6.关闭资源
try {
stmt.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
查询(select)
// 声明jdbc变量
Connection conn = null;
Statement stmt = null;
// 声明jdbc参数
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123456";
try {
// 1 加载驱动类
Class.forName(driver);
// 2.获取数据库连接对象(连接指定数据库)
conn = DriverManager.getConnection(url, user, password);
// 3.创建sql命令对象(编译和发送sql命令给数据库)
stmt = conn.createStatement();
// 4.创建sql命令
String sql = "select * from user";
// 5.指定sql命令
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getInt(1) + " " + rs.getString("username") + " " + rs.getString(3));
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 6.关闭资源
try {
stmt.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
JDBC的事务管理
事务:一个事件的完成需要几个子操作的联合完成。只要有一个子操作执行失败,则数据回滚到原始状态,都成功则提交数据。
JDBC默认为自动提交事务。进行增删改操作时应将其设置为手动提交。
conn.setAutoCommit(false);
默认值为true,自动提交。 false 为手动提交。
使用try catch进行SQL命令执行提交和回滚。
try {
conn.commit();
} catch (SQLException e) {
conn.rollback();
e.printStackTrace();
}
try 中使用 conn.commit() 进行数据提交,若报错则在 catch 中使用 conn.rollback() 进行事务回滚。
使用PreparedStatement对象进行数据库操作
PreparedStatement对象与Statement对象的比较
Statement对象进行数据库操作时可能会出现 sql 注入的风险。
preparedStatement对象在sql语句中使用占位符,可以防止sql注入。可以预编译,批量执行同一条SQL语句时效率远大于Statement对象。
// statement对象执行sql语句
Statement stmt = conn.createStatement();
String sql = "insert into user values(13,'王13','wang13')";
int i = stmt.executeUpdate(sql);
// preparedStatement对象执行sql语句
String sql = "insert into user values(?,?,?)";
PraparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, 15);
ps.setString(2, "王15");
ps.setString(3, "123456");
int i = ps.executeUpdate();
优化封装代码
driver=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:3306/test user=root password=123456
db.properties
1 import java.io.IOException;
2 import java.io.InputStream;
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.PreparedStatement;
6 import java.sql.ResultSet;
7 import java.sql.SQLException;
8 import java.sql.Statement;
9 import java.util.Properties;
10
11 public class JUtil {
12 private static String driver;
13 private static String url;
14 private static String user;
15 private static String password;
16
17 static {
18 // 创建properties对象获取属性文件的内容
19 Properties p = new Properties();
20 // 获取属性文件的读取对象流
21 InputStream is = JUtil.class.getResourceAsStream("/db.properties");
22 try {
23 // 加载属性配置文件
24 p.load(is);
25 // 获取jdbc参数
26 driver = p.getProperty("driver");
27 url = p.getProperty("url");
28 user = p.getProperty("user");
29 password = p.getProperty("password");
30 // 加载驱动
31 Class.forName(driver);
32 } catch (IOException e) {
33 // TODO Auto-generated catch block
34 e.printStackTrace();
35 } catch (ClassNotFoundException e) {
36 // TODO Auto-generated catch block
37 e.printStackTrace();
38 }
39 }
40
41 // 获取Connection对象
42 public static Connection getConn() {
43 Connection conn = null;
44 try {
45 conn = DriverManager.getConnection(url, user, password);
46 } catch (SQLException e) {
47 // TODO Auto-generated catch block
48 e.printStackTrace();
49 }
50 return conn;
51 }
52
53 // 获取PreparedStatement对象
54 public static PreparedStatement getPre(Connection conn,String sql) {
55 PreparedStatement ps = null;
56 try {
57 ps = conn.prepareStatement(sql);
58 } catch (SQLException e) {
59 // TODO Auto-generated catch block
60 e.printStackTrace();
61 }
62 return ps;
63 }
64
65 // 关闭资源
66 public static void closeAll(Statement stmt,Connection conn) {
67 try {
68 stmt.close();
69 } catch (SQLException e) {
70 // TODO Auto-generated catch block
71 e.printStackTrace();
72 }
73 try {
74 conn.close();
75 } catch (SQLException e) {
76 // TODO Auto-generated catch block
77 e.printStackTrace();
78 }
79 }
80 }
工具类Jutil
1 /**
2 * 封装DML
3 * @param sql sql语句
4 * @param objs 参数数组
5 * @return i 大于等于 1 时执行成功,等于 0 时执行失败。
6 */
7 private int executeDML(String sql,Object ... objs) {
8 Connection conn = null;
9 PreparedStatement ps = null;
10 int i= 0;
11 try {
12 // 创建连接对象
13 conn = JUtil.getConn();
14 // 手动提交事物
15 conn.setAutoCommit(false);
16 // 获得sql语句及参数
17 ps = JUtil.getPre(conn, sql);
18 // 给占位符赋值
19 for(int j = 0; j < objs.length; j++) {
20 ps.setObject(j+1, objs[j]);
21 }
22 // 执行sql命令
23 i = ps.executeUpdate();
24 // 提交
25 conn.commit();
26 } catch (SQLException e) {
27 try {
28 // 回滚
29 conn.rollback();
30 } catch (SQLException e1) {
31 e1.printStackTrace();
32 }
33 } finally {
34 JUtil.closeAll(ps, conn);
35 }
36 return i;
37 }
封装DML(增删改)
1 /**
2 * 增加
3 * @param id
4 * @param name
5 * @param pwd
6 * @return i 大于等于 1 时执行成功,等于 0 时执行失败。
7 */
8 public int insert(int id,String name,String pwd) {
9 String sql = "insert into user values(?,?,?)";
10 int i = executeDML(sql,id,name,pwd);
11 return i;
12 }
insert增加
1 /**
2 * 修改
3 * @param id
4 * @param name
5 * @param pwd
6 * @return i 大于等于 1 时执行成功,等于 0 时执行失败。
7 */
8 public int update(int id,String name,String pwd) {
9 String sql = "update user set username=? where id=?";
10 int i = executeDML(sql,name,id);
11 return i;
12 }
update修改
1 /**
2 * 删除
3 * @param id
4 * @param name
5 * @param pwd
6 * @return i 大于等于 1 时执行成功,等于 0 时执行失败。
7 */
8 public int delete(int id,String name,String pwd) {
9 String sql = "delete from user where id=?";
10 int i = executeDML(sql, id);
11 return i;
12 }
delete删除
1 /**
2 * 查询
3 * @return
4 */
5 public List<User> select() {
6 Connection conn = JUtil.getConn();
7 String sql = "select * from user";
8 PreparedStatement ps = JUtil.getPre(conn, sql);
9 List<User> us = new ArrayList<User>();
10 try {
11 ResultSet rs = ps.executeQuery();
12 while(rs.next()) {
13 User u = new User();
14 u.setId(rs.getInt(1));
15 u.setName(rs.getString(2));
16 u.setPwd(rs.getString(3));
17 us.add(u);
18 }
19 } catch (SQLException e) {
20 e.printStackTrace();
21 } finally {
22 JUtil.closeAll(ps, conn);
23 }
24 return us;
25 }
select查询
常见的JDBC错误
1. ClassNotFoundException:
驱动类未找到
2. java.sql.SQLException: No suitable driver found for :mysql://localhost:3306/test
URL错误
3. No database selected
未找到数据库
4. Access denied for user 'root1'@'localhost' (using password: YES)
用户名或密码错误
5. java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax;
sql语句错误
6. java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '13' for key 'PRIMARY'
主键冲突