JDBC
什么是JDBC
JDBC(Java DataBase Connectivity, Java数据库连接) ,是一种用于执行SQL语句的Java API,为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成
连接数据库
mysql8 之前连接
数据库驱动名:com.mysql.jdbc.Driver
url连接:jdbc:mysql://127.0.0.1:3306/mydb
public class test{
public static void main(String[] args){
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://127.0.0.1:3306/mydb";
String user="root";
String password="root";
Connection conn = DriverManager.getConnection(url,user,password);
}
}
mysql8之后连接
数据库驱动名:com.mysql.cj.jdbc.Driver
url连接:jdbc:mysql://127.0.0.1:3306/mydbseSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
public class test{
public static void main(String[] args){
* url 同一资源定位符
* 协议 jdbc:mysql:
* ip地址 127.0.0.1/localhost
* 端口号 3306
* 具体的资源路径 mydb
* useSSL=false 不使用SSL加密机制
* &useUnicode=true 使用unicode字符集
* &characterEncoding=utf8 使用utf8作为通信字符集
* &serverTimezone=Asia/Shanghai 确定时区为 Asia/Shanghai
* user 账号 root
* password 密码 root
* */
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb?seSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
Connection conn = DriverManager.getConnection(url,user,password);
}
}
常见异常
java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver2
未添加jar包 或者 路径错误
SQLException: No suitable driver found for jdbcs
协议错误
CommunicationsException: Communications link failure
通信失败
SQLException: Access denied for user ‘root’@‘localhost’ (using password: YES)
拒绝访问 密码错误
SQLNonTransientConnectionException: Public Key Retrieval is not allowed
不允许检索公钥 用户名错误
SQLIntegrityConstraintViolationException: Duplicate entry ‘50’ for key ‘PRIMARY’
主键重复输入
executeQuert() 和 executeUpdate() 区别
执行查询命令 : executeQuert()
执行增删改命令 :executeUpdate()
ResultSet(结果解)接口
ResultSet对象 接收executeQuert() 的返回值
JDBC Statement 接口
用于发送SQL语句到数据库中,或理解为执行sql命令
添加数据(insert)
public class TestInsert {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver2");
//2.创建数据库连接
String url = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
Connection conn = DriverManager.getConnection(url, user, pwd);
//3.创建SQL命令发送器
Statement st = conn.createStatement();
String sql = "insert into dept values(50,'中部','北京')";
//4.通过Statement发送SQL命令并得到结果
int rows = st.executeUpdate(sql);
System.out.println("执行完毕,对数据中" + rows + "行数据产生了影响");
//5.关闭资源
st.close();
conn.close();
}
}
修改数据(update)
public class TestUpdate {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.创建数据库连接
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
Connection conn = DriverManager.getConnection(url, user, pwd);
//3.创建SQL命令发送器
Statement st = conn.createStatement();
String sql = "update dept set dname='销售部'where deptno=50 ";
//4.通过Statement发送SQL命令并得到结果
int rows = st.executeUpdate(sql);
System.out.println("执行完毕,对数据中" + rows + "行数据产生了影响");
//5.关闭资源
st.close();
conn.close();
}
}
删除数据(delete)
public class TestDelete {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.创建数据库连接
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
Connection conn = DriverManager.getConnection(url, user, pwd);
//3.创建SQL命令发送器
Statement st = conn.createStatement();
String sql = "delete from dept where deptno=50";
//4.通过Statement发送SQL命令并得到结果
int rows = st.executeUpdate(sql);
System.out.println("执行完毕,对数据中" + rows + "行数据产生了影响");
//5.关闭资源
st.close();
conn.close();
}
}
查询数据(select)
public class TestExecuteQuery {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//建立练级
Connection conn = DriverManager.getConnection(url, user, pwd);
//创建sql命令发送器
Statement st = conn.createStatement();
String sql = "select * from emp";
//发送sql命令 并返回数据
ResultSet rs = st.executeQuery(sql);
//ResultSet 使用方式2
while (rs.next()) {
//获取行数据
int enmno = rs.getInt(1);
String eName=rs.getString(2);
String job=rs.getString(3);
int mgr = rs.getInt(4);
Date hireDate= rs.getDate(5);
double sal= rs.getDouble(6);
double comm= rs.getDouble(7);
int deptNo =rs.getInt(8);
StringBuilder str = new StringBuilder();
str.append(enmno+" ").append(eName+" ").append(job+" ").append(mgr+" ").append(hireDate+" ").append(sal+" ").append(comm+" ").append(deptNo+" ");
System.out.println(str.toString());
}
rs.close();
st.close();
conn.close();
//ResultSet 使用方式2
/*while (rs.next()) {
int enmno = rs.getInt("EMPNO");
String eName=rs.getString("ENAME");
String job=rs.getString("JOB");
int mgr = rs.getInt("MGR");
Date hireDate= rs.getDate("HIREDATE");
double sal= rs.getDouble("SAL");
double comm= rs.getDouble("COMM");
int deptNo =rs.getInt("DEPTNO");
StringBuilder str = new StringBuilder();
str.append(enmno+" ").append(eName+" ").append(job+" ").append(mgr+" ").append(hireDate+" ").append(sal+" ").append(comm+" ").append(deptNo+" ");
System.out.println(str.toString());
}
*/
}
}
将数据库中的数据多条存入实体类中 并遍历数据
public class TestExecuteQuery2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
List<Emp> list = getAllEmp();
showEmp(list);
}
public static List<Emp> getAllEmp() {
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
ResultSet rs = null;
Connection conn = null;
Statement st = null;
List<Emp> list = new ArrayList<>();
try {
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//建立连接
conn = DriverManager.getConnection(url, user, pwd);
//创建sql命令发送器
st = conn.createStatement();
String sql = "select * from emp";
//发送sql命令 本返回数据
rs = st.executeQuery(sql);
while (rs.next()) {
//获取行数据
int enmno = rs.getInt("EMPNO");
String eName = rs.getString("ENAME");
String job = rs.getString("JOB");
int mgr = rs.getInt("MGR");
Date hireDate = rs.getDate("HIREDATE");
double sal = rs.getDouble("SAL");
double comm = rs.getDouble("COMM");
int deptNo = rs.getInt("DEPTNO");
Emp emp = new Emp(enmno,eName,job,mgr,hireDate,sal,comm,deptNo);
list.add(emp);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
if (null != rs) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != st) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return list;
}
/**
* 遍历集合
* */
public static void showEmp(List<Emp> list){
for(Emp e:list){
System.out.println(e);
}
}
}
sql注入风险
SQL语句中拼接的内容破坏了 SQL语句原有的判断逻辑
select * from user where username='lisi' and password='ll' or '1'='1'
使用Statement
public static User login(String username,String password) {
User users = null;
Connection conn=null;
int n=0;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
conn = DriverManager.getConnection(url, user, pwd);
Statement st = conn.createStatement();
String sql = "select * from user where username='"+username+"' and password='"+password+"'";
System.out.println(sql);
ResultSet rs = st.executeQuery(sql);
if(rs.next()){
int id = rs.getInt("id");
String userName= rs.getString("username");
String pwd2 =rs.getString("password");
users= new User(id,userName,pwd2);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != conn){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return users;
}
sql注入风险解决方式:使用PreparedStatement
public static User login2(String username,String password) {
User users = null;
Connection conn=null;
int n=0;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
conn = DriverManager.getConnection(url, user, pwd);
String sql = "select * from user where username='"+username+"' and password='"+password+"'";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
if(rs.next()){
int id = rs.getInt("id");
String userName= rs.getString("username");
String pwd2 =rs.getString("password");
users= new User(id,userName,pwd2);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != conn){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return users;
}
JDBC PreparedStatement 接口
Statement 和 PreparedStatement 区别和联系
联系 :PreparedStatement extends Statement
区别:1.PreparedStatment安全性高,可以避免SQL注入
2.PreparedStatment简单不繁琐,不用进行字符串拼接
3.PreparedStatment性能高,用在执行多个相同数据库DML操作时
添加数据(insert)
public class TestPreparedStatement {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PWD = "root";
public static void main(String[] args)throws Exception {
insert(66,"asdfaf","jiadjfa");
}
/**
* 功能描述:添加
* @param:
* @return:
*/
public static void insert(int deptno,String dname,String loc) throws Exception{
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USER, PWD);
String sql = "insert into dept values(?,?,?) ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,deptno);
ps.setString(2,dname);
ps.setString(3,loc);
int n = ps.executeUpdate();
ps.close();
conn.close();
}
}
修改数据(update)
public class TestPreparedStatement {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PWD = "root";
public static void main(String[] args)throws Exception {
insert(66,"asdfaf","jiadjfa");
}
/**
* 功能描述:修改
* @param:
* @return:
*/
public static void update(int deptno,String dname) throws Exception{
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USER, PWD);
String sql = "update dept set dname=? where deptno=? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,dname);
ps.setInt(2,deptno);
int n = ps.executeUpdate();
ps.close();
conn.close();
}
}
删除数据(delete)
public class TestPreparedStatement {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PWD = "root";
public static void main(String[] args)throws Exception {
insert(66,"asdfaf","jiadjfa");
}
/**
* 功能描述:删除
* @param:
* @return:
*/
public static void delete(int deptno) throws Exception{
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USER, PWD);
String sql = "delete from dept where deptno=? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,deptno);
int n = ps.executeUpdate();
ps.close();
conn.close();
}
}
查询数据(select)
public class TestPreparedStatement {
public static final String DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://127.0.0.1:3306/mydb? useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
private static final String USER = "root";
private static final String PWD = "root";
public static void main(String[] args)throws Exception {
insert(66,"asdfaf","jiadjfa");
}
/**
* 功能描述:模糊查询
* @param:
* @return:
*/
public static void find(String n) throws Exception {
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USER, PWD);
String sql = "select * from emp where ename like ? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,"%"+n+"%");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
int enmno = rs.getInt("EMPNO");
String eName=rs.getString("ENAME");
String job=rs.getString("JOB");
int mgr = rs.getInt("MGR");
Date hireDate= rs.getDate("HIREDATE");
double sal= rs.getDouble("SAL");
double comm= rs.getDouble("COMM");
int deptNo =rs.getInt("DEPTNO");
StringBuilder str = new StringBuilder();
str.append(enmno+" ").append(eName+" ").append(job+" ").append(mgr+" ").append(hireDate+" ").append(sal+" ").append(comm+" ").append(deptNo+" ");
System.out.println(str.toString());
}
rs.close();
ps.close();
conn.close();
}
}
JDBC事务
禁止事务自动提交(setAutoCommit)
setAutoCommit(false);
手动提交事务(commit)
conn.commit()
回滚(rollback)
conn.rollback()
public class TestTransaction {
public static void main(String[] args) {
//1.加载驱动
PreparedStatement pst = null;
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String user = "root";
String pwd = "root";
//2.创建数据库连接
conn = DriverManager.getConnection(url, user, pwd);
//禁止事务自动提交
conn.setAutoCommit(false);
String sql = "update account set money= money-100 where username=?";
pst = conn.prepareStatement(sql);
pst.setString(1, "张三");
//发送SQL命令
pst.executeUpdate();
sql = "update account set money=money+100 where username=?";
pst = conn.prepareStatement(sql);
pst.setString(1, "李四");
//发送SQL命令
pst.executeUpdate();
} catch (ClassNotFoundException e) {
try {
//回滚
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != conn) {
try {
//提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
//关闭资源
if (null != pst) {
try {
pst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
JDBC API 总结
Connection接口 方法
代表数据库连接
void |
close() 立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。 |
---|---|
void |
commit() 使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 对象当前持有的所有数据库锁。 |
Statement |
createStatement() 创建一个 Statement 对象来将 SQL 语句发送到数据库。 |
CallableStatement |
prepareCall( Stringsql) 创建一个 CallableStatement 对象来调用数据库存储过程。 |
PreparedStatement |
prepareStatement( Stringsql) 创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。 |
PreparedStatement |
[prepareStatement](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/sql/Connection.html#prepareStatement(java.lang.String, int))( Stringsql, int autoGeneratedKeys) 创建一个默认 PreparedStatement 对象,该对象能获取自动生成的键。 |
void |
rollback() 取消在当前事务中进行的所有更改,并释放此 Connection 对象当前持有的所有数据库锁。 |
void |
setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。 |
DriverManager类 方法
管理一组 JDBC 驱动程序的基本服务
方法摘要 | |
---|---|
static Connection |
getConnection( Stringurl) 试图建立到给定数据库 URL 的连接。 |
static Connection |
[getConnection](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/sql/DriverManager.html#getConnection(java.lang.String, java.util.Properties))( Stringurl, Propertiesinfo) 试图建立到给定数据库 URL 的连接。 |
static Connection |
[getConnection](mk:@MSITStore:C:\Users\Administrator\Desktop\JDK_API_1_6_zh_CN.CHM::/java/sql/DriverManager.html#getConnection(java.lang.String, java.lang.String, java.lang.String))( Stringurl, Stringuser, Stringpassword) 试图建立到给定数据库 URL 的连接。 |
Statement接口 方法
用于将 SQL 语句发送到数据库中,或理解为执行sql语句
方法 | 作用 |
---|---|
ResultSet executeQuery(String sql) | 执行SQL查询并获取到ResultSet对象 |
boolean execute(String sql) | 可以执行任意SQL语句,然后获得一个布尔值,表示是否返回ResultSet |
int executeUpdate(String sql) | 可以执行插入、删除、更新等操作,返回值是执行该操作所影响的行数 |
ResultSet接口 方法
ResultSet里的数据一行一行排列,每行有多个字段,且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环
ResultSet对象自动维护指向当前数据行的游标。每调用一次next()方法,游标向下移动一行。
方法名 | 说 明 |
---|---|
boolean next() | 将光标从当前位置向下移动一行 |
boolean previous() | 游标从当前位置向上移动一行 |
void close() | 关闭ResultSet 对象 |
int getInt(int colIndex) | 以int形式获取结果集当前行指定列号值 |
int getInt(String colLabel) | 以int形式获取结果集当前行指定列名值 |
float getFloat(int colIndex) | 以float形式获取结果集当前行指定列号值 |
Float getFloat(String colLabel) | 以float形式获取结果集当前行指定列名值 |
String getString(int colIndex) | 以String 形式获取结果集当前行指定列号值 |
StringgetString(String colLabel) | 以String形式获取结果集当前行指定列名值 |