一、JDBC简单介绍
JDBC(Java DataBase Connectivity)是Java和数据库之间的一个桥梁,由一组用Java语言编写的类和接口组成。可理解为,数据库是一个仓库,而Java是取货员,JDBC则是取货员的证件,且一个取货员需要一个独有的证件(当然拿身份证和别的啥啥的也可以证明取货员的身份,但是那样核对取货员的身份很麻烦。因此为了避免代码的冗长,我们就可以装载JDBC数据库驱动包,使大家的形式都一样,这样就很容易便捷核对身份)。
二、JDBC基本使用流程
以下是JDBC使用的基本操作,除特殊说明外,不要更改啦!
(此部分载入JDBC驱动,需要连接MySQL,具体操作请参考这篇博客Intellij IDEA载入JDBC驱动,连接Mysql)
package JavaExample;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
//以sql插入语句为例
public class TestInsert {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//加载驱动类,即程序入口,将数据库相关类都加载至内存
//forname中的String是包名+类名
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接对象(连接指定的数据库),至此连接通道完毕
//此部分语句为:Connection conn= DriverManager.getConnection("url", "username", "password");
//url是要连接的数据库地址,其中url中的moon是数据库名;username和password是用户名及密码
Connection conn= DriverManager.getConnection("jdbc:mysql://localhost/moon?useSSL=false&serverTimezone=UTC&charactorEncoding=UTF-8","root","2019012660Moon");
//获取sql命令对象(编译并发送sql命令给数据库)
Statement stmt=conn.createStatement();
//创建sql命令,括号中输入正常的插入语句即可
String sql="insert into city values (此是插入的数据嗷)";
//执行sql命令,声明i,如果没有执行成功,返回-1;如果执行成功,返回更改了几条数据
int i=stmt.executeUpdate(sql);
System.out.println("执行结果"+i);
//关闭资源
stmt.close();
conn.close();
}
}
三、JDBC常见错误
- ClassNotFoundException:未找到驱动类
错误地方在于:Class.forName(“com.mysql.jdbc.Driver”); - SQLException:url,username或是password有错误
错误地方在于:Connection conn= DriverManager.getConnection(“url”, “username”, “password”); - SQLSyntaxErrorException:sql语句错误
错误地方在于:String sql=" "; - SQLIntegrityConstraintViolationException:主键冲突
四、JDBC代码优化
package JavaExample;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Example7_6 {
public static void main(String[] args) {
//先声明conn和stmt,以便最后关闭资源
Connection conn=null;
Statement stmt=null;
//声明JDBC参数,此处请看加载驱动类的部分
String driver="com.mysql.jdbc.Driver";
//声明数据库的url,username,password
String url="jdbc:mysql://localhost/moon?useSSL=false&serverTimezone=UTC&charactorEncoding=UTF-8";
String username="root";
String password="2019012660Moon";
try{
//加载驱动类
Class.forName(driver);
//获取数据库连接对象
conn= DriverManager.getConnection(url,username,password);
//获取sql命令对象
stmt=conn.createStatement();
//创建sql命令
String sql="insert into city values (此是插入的数据嗷)";
//执行sql命令
int i=stmt.executeUpdate(sql);
System.out.println("执行结果"+i);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
五、JDBC事物管理
简单说一下什么是事物:
一个事件的完成需要几个子操作的联合完成,只要有一个子操作执行失败,则数据回滚到原始状态;若子操作都成功,则提交数据。
现在我们要写几行代码来实现一个业务:张三给李四汇款1000元。
数据库如下图所示:
此时,当张三给李四汇款1000元时,有两句sql语句需要执行:
- 张三的money由10000变为9000元。
- 李四的money由10000变为11000元。
在执行此项业务时可能会遇到此问题:如果第二句sql语句出现错误,即李四的money没有从10000元变为11000元,该如何解决。也就是张三明明已经汇款给李四,但李四的账户却没有接收到。由此,我们就可以感受到事务回滚的好处:当第二句sql语句出现错误时,被更改的表就会回到初始状态,即张三没有汇款,而李四也没有收到钱。
具体代码如下:
package com.jdbc.translation;
/*
*
* JDBC事务管理
* 示例:
* 张三给李四转账1000元
* 注意:
* JDBC自动提交数据
* 问题:
* 如果业务的处理过程中,某条sql语句执行失败,但是数据部分已更改,无法回到初始状态
* 解决方法:
* 设置JDBC为手动提交,sql语句执行成功后,统一提交
* 使用方法:
* conn.setAutoCommit(false);设置手动提交
* 使用try catch进行sql命令异常处理(try提交数据,catch进行回滚)
*
*/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestTranslation {
public static void main(String[] args) {
Connection conn=null;
Statement stmt=null;
String driver="com.mysql.jdbc.Driver";
String url="jdbc:mysql://localhost/moon?useSSL=false&serverTimezone=UTC&charactorEncoding=UTF-8";
String username="root";
String password="2019012660Moon";
try {
//加载驱动
Class.forName(driver);
//创建连接对象
conn = DriverManager.getConnection(url, username, password);
//设置事物为手动提交,与后续rollback()结合
//如果执行期间有错误,则报错同时进行回滚(即回到初始状态)
conn.setAutoCommit(false);
//创建sql命令对象
stmt = conn.createStatement();
//创建sql命令
String sql1="update bank set money=money-1000 where name='张三'";
String sql2="update bank set money=money+1000 where name='李四'";
//执行sql命令
try {
int i1=stmt.executeUpdate(sql1);
int i2=stmt.executeUpdate(sql2);
System.out.println(i1+"---------"+i2);
conn.commit();
} catch (Exception e) {
//数据回滚
conn.rollback();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
六、小例子:更新昵称
为了便于不同用户操作数据库,我们将数据库代码封装起来,便于维护。
(其中此代码中的数据操作参考上张图片)
//此部分是有关数据库的封装
package com.jdbc.daolmpl;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class BankDaolmpl {
public int updateName(String newName) {
Connection conn=null;
Statement stmt=null;
int i=-1;
String driver="com.mysql.jdbc.Driver";
String url="jdbc:mysql://localhost/moon?useSSL=false&serverTimezone=UTC&charactorEncoding=UTF-8";
String username="root";
String password="2019012660Moon";
try {
//加载驱动
Class.forName(driver);
//创建连接对象
conn = DriverManager.getConnection(url, username, password);
//设置事物为手动提交,与后续rollback()结合
//如果执行期间有错误,则报错同时进行回滚(即回到初始状态)
conn.setAutoCommit(false);
//创建sql命令对象
stmt = conn.createStatement();
//创建sql命令
String sql="update bank set name='"+newName+"' where name='张三'";
//执行sql命令
try {
i=stmt.executeUpdate(sql);
conn.commit();
} catch (Exception e) {
//数据回滚
conn.rollback();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
return i;
}
}
}
//此部分是用户的具体需求操作
package com.jdbc.dao;
import com.jdbc.daolmpl.BankDaolmpl;
import java.util.Scanner;
public class UpdateName {
public static void main(String[] args) {
//创建Scanner对象,获取用户数据
Scanner reader=new Scanner(System.in);
System.out.println("请输入新的昵称:");
String newName=reader.nextLine();
//调用数据库进行操作
BankDaolmpl person=new BankDaolmpl();
int i=person.updateName(newName);
//判断是否更改成功
if (i>0) {
System.out.println("更改成功");
} else {
System.out.println("更改失败");
}
}
}