JDBC概念和数据库驱动程序
- A: JDBC概念和数据库驱动程序
- a: JDBC概述
- JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范
- JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
- JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,
设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。 - 我们使用的是mysql的驱动mysql-connector-java-5.1.39-bin.jar
- b: 总结
- JDBC是java提供给开发人员的一套操作数据库的接口
- 数据库驱动就是实现该接口的实现类
- a: JDBC概述
JDBC原理
- a: 描述
* Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动
* JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!
每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。
导入mysql数据库驱动程序jar包
- A: 导入mysql数据库驱动程序jar包
* a: 步骤
* 创建lib目录,用于存放当前项目需要的所有jar包
* 选择jar包,右键执行build path / Add to Build Path
JDBC的开发步骤
- A: JDBC的开发步骤
* a: 步骤介绍
1.注册驱动
告知JVM使用的是哪一个数据库的驱动
2.获得连接
使用JDBC中的类,完成对MySQL数据库的连接
3.获得语句执行平台
通过连接对象获取对SQL语句的执行者对象
4.执行sql语句
使用执行者对象,向数据库执行SQL语句
获取到数据库的执行后的结果
5.处理结果
6.释放资源 一堆close()
执行insert语句获取结果集
* a: 案例代码
public class JDBCDemo {
public static void main(String[] args)throws ClassNotFoundException,SQLException{
//1.注册驱动 反射技术,将驱动类加入到内容
// 使用java.sql.DriverManager类静态方法 registerDriver(Driver driver)
// Diver是一个接口,参数传递,MySQL驱动程序中的实现类
//DriverManager.registerDriver(new Driver());
//驱动类源代码,注册2次驱动程序
Class.forName("com.mysql.jdbc.Driver");
//2.获得数据库连接 DriverManager类中静态方法
//static Connection getConnection(String url, String user, String password)
//返回值是Connection接口的实现类,在mysql驱动程序
//url: 数据库地址 jdbc:mysql://连接主机IP:端口号//数据库名字
String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=UTF-8";
String username="root";
String password="123";
Connection con = DriverManager.getConnection(url, username, password);
//3.获得语句执行平台, 通过数据库连接对象,获取到SQL语句的执行者对象
// con对象调用方法 Statement createStatement() 获取Statement对象,将SQL语句发送到数据库
// 返回值是 Statement接口的实现类对象,,在mysql驱动程序
Statement stat = con.createStatement();
// 4.执行sql语句
// 通过执行者对象调用方法执行SQL语句,获取结果
// int executeUpdate(String sql) 执行数据库中的SQL语句, insert delete update
// 返回值int,操作成功数据表多少行
int row = stat.executeUpdate
("INSERT INTO sort(sname,sprice,sdesc) VALUES('汽车用品',50000,'疯狂涨价')");
System.out.println(row);
//6.释放资源 一堆close()
stat.close();
con.close();
}
}
执行select语句获取结果集
* a: 案例代码
public class JDBCDemo1 {
public static void main(String[] args) throws Exception{
//1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/mybase?useUnicode=true&characterEncoding=UTF-8";
String username="root";
String password="123";
Connection con = DriverManager.getConnection(url, username, password);
//3 .获取执行SQL 语句对象
Statement stat = con.createStatement();
// 拼写查询的SQL
String sql = "SELECT * FROM sort";
//4. 调用执行者对象方法,执行SQL语句获取结果集
// ResultSet executeQuery(String sql) 执行SQL语句中的select查询
// 返回值ResultSet接口的实现类对象,实现类在mysql驱动中
ResultSet rs = stat.executeQuery(sql);
//5 .处理结果集
// ResultSet接口方法 boolean next() 返回true,有结果集,返回false没有结果集
while(rs.next()){
//获取每列数据,使用是ResultSet接口的方法 getXX方法参数中,建议写String列名
System.out.println(rs.getInt("sid")+" "+rs.getString("sname")+
" "+rs.getDouble("sprice")+" "+rs.getString("sdesc"));
}
rs.close();
stat.close();
con.close();
}
}
PrepareStatement接口预编译SQL语句执行修改
* 案例代码
/*
* 使用PrepareStatement接口,实现数据表的更新操作
*/
public class JDBCDemo {
public static void main(String[] args) throws Exception{
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3296/mybase";
String username="root";
String password="123";
Connection con = DriverManager.getConnection(url, username, password);
//拼写修改的SQL语句,参数采用?占位
String sql = "UPDATE sort SET sname=?,sprice=? WHERE sid=?";
//调用数据库连接对象con的方法prepareStatement获取SQL语句的预编译对象
PreparedStatement pst = con.prepareStatement(sql);
//调用pst的方法setXXX设置?占位
pst.setObject(1, "汽车美容");
pst.setObject(2, 49988);
pst.setObject(3, 7);
//调用pst方法执行SQL语句
pst.executeUpdate();
pst.close();
con.close();
}
}
PrepareStatement接口预编译SQL语句执行查询
* a: 案例代码
/*
* PrepareStatement接口实现数据表的查询操作
*/
public class JDBCDemo1 {
public static void main(String[] args) throws Exception{
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3296/mybase";
String username="root";
String password="123";
Connection con = DriverManager.getConnection(url, username, password);
String sql = "SELECT * FROM sort";
PreparedStatement pst = con.prepareStatement(sql);
//调用pst对象的方法,执行查询语句,Select
ResultSet rs=pst.executeQuery();
while(rs.next()){
System.out.println(rs.getString("sid")+" "+rs.getString("sname")+" "+rs.getString("sprice")+" "+rs.getString("sdesc"));
}
rs.close();
pst.close();
con.close();
}
}
JUnit:
public class TestDemo {
Connection connection = null;
PreparedStatement preparedStatement = null;
@Before
public void init() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mybase?useUnicode=true&characterEncoding=UTF-8","root","root");
System.out.println("init");
}
@After
public void after() throws SQLException {
preparedStatement.close();
connection.close();
}
@Test
public void test_login() throws ClassNotFoundException, SQLException {
// write your code here
System.out.println(connection);
Scanner(System.in);
String username = "zhangsan";
String password = "1233";
preparedStatement
= connection.prepareStatement("select * from users where username = ? and password = ?");
preparedStatement.setString(1,username);
preparedStatement.setString(2,password);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next())
{
System.out.println("登录成功");
}
else
{
System.out.println("登录失败");
}
// 6.释放资源 一堆close()
resultSet.close();
}
//测试用例
@Test
public void test_update() throws SQLException, ClassNotFoundException {
preparedStatement
= connection.prepareStatement("update users set username = ? where id = ?");
preparedStatement.setString(1,"张三丰");
preparedStatement.setInt(2,1);
int nRows = preparedStatement.executeUpdate();
}
}
JDBC的工具类和测试
* a: 案例代码
//JDBCUtils工具类代码
public class JDBCUtils {
private JDBCUtils(){}
private static Connection con ;
static{
try{
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mybase";
String username="root";
String password="root";
con = DriverManager.getConnection(url, username, password);
}catch(Exception ex){
throw new RuntimeException(ex+"数据库连接失败");
}
}
/*
* 定义静态方法,返回数据库的连接对象
*/
public static Connection getConnection(){
return con;
}
public static void close(Connection con,Statement stat){
if(stat!=null){
try{
stat.close();
}catch(SQLException ex){}
}
if(con!=null){
try{
con.close();
}catch(SQLException ex){}
}
}
public static void close(Connection con,Statement stat , ResultSet rs){
if(rs!=null){
try{
rs.close();
}catch(SQLException ex){}
}
if(stat!=null){
try{
stat.close();
}catch(SQLException ex){}
}
if(con!=null){
try{
con.close();
}catch(SQLException ex){}
}
}
}
//测试JDBCUtils工具类的代码
public class TestJDBCUtils {
public static void main(String[] args)throws Exception {
Connection con = JDBCUtils.getConnection();
PreparedStatement pst = con.prepareStatement("SELECT sname FROM sort");
ResultSet rs = pst.executeQuery();
while(rs.next()){
System.out.println(rs.getString("sname"));
}
JDBCUtils.close(con, pst, rs);
}
}
主方法:
Connection connection = JDBCUtils.getConnection();
JDBCUtils.close(connection,preparedStatement,resultSet);
jdbc事务处理
案例:转账操作,输入;两个用户名,然后输出一个转账金额,操作为:第一个用户给第二个用户转账指定的金额。
在金额从A用户转出完了,再转入到B账户的过程中如果系统出现故障,那么金额就不会转入到B账户了。但是A事务已经提交(只要执行了DML操作jdbc默认就是自动提交事务的)。这就造成了金额凭空丢失的问题。所以,需要让所有的操作在同一个事务中,中间任何一部出现问题就需要事务回滚,能执行到最后才能进行事务提交。
try{
//关闭自动提交
//操作1
//操作2
//提交事务
}catch(){
//回滚事务
}
这样做就能保障一组操作的完整性.
public class JDBCTrans {
public static void main(String[] args) {
Connection connection = null;
try {
Scanner scanner = new Scanner(System.in);
System.out.println("输入转出账号:");
String out = scanner.nextLine();
System.out.println("输入转入账号:");
String in = scanner.nextLine();
System.out.println("输入转账金额");
int account = scanner.nextInt();
connection=DBUtil.getConnection();
//设置事务不自动提交
connection.setAutoCommit(false);
//转出
String outSql="UPDATE userinfo "
+ "SET account=account-? "
+ "WHERE username=?";
PreparedStatement preparedStatement = connection.prepareStatement(outSql);
preparedStatement.setInt(1, account);
preparedStatement.setString(2, out);
int m = preparedStatement.executeUpdate();
System.out.println("---");
if(m>0){
System.out.println("转出成功");
}else {
System.out.println("转出失败");
//不再进行转入
return;
}
//转入
String inSql="UPDATE userinfo "
+ "SET account=account+?"
+ "WHERE username=?";
preparedStatement = connection.prepareStatement(inSql);
preparedStatement.setInt(1, account);
preparedStatement.setString(2, in);
int n = preparedStatement.executeUpdate();
if(n>0){
System.out.println("转入成功");
connection.commit();
}else {
System.out.println("转入失败");
//回滚事务
connection.rollback();
}
} catch (Exception e) {
//出现异常回滚事务
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
DBUtil.closeConnection();
}
}
}
public class JDBCTransactionDemo {
public static void main(String[] args) throws SQLException {
Connection connection = JDBCUtils.getConnection();
connection.setAutoCommit(false);
try {
PreparedStatement preparedStatement
= connection.prepareStatement("update users set money = money - 2000 where id = 3");
preparedStatement.executeUpdate();
preparedStatement
= connection.prepareStatement("update users set money = money + 2000 where id = 4");
preparedStatement.executeUpdate();
connection.commit();
} catch (Exception e) {
connection.rollback();
}
}
}
jdbc之批处理
批操作可以一次性向数据库端发送若干SQL语句,从而减少与数据库服务端的网络通信,提高执行效率。
当大批量执行SQL语句时,影响效率的2个因素:
1:事务,事务越多速度越慢(事务最好一次提交);
2:网络调用,网络调用越多速度越慢(这里可以使用缓存解决);
需求:向数据库中userinfo表插入10000条数据
自动提交事务,不添加缓存测试:
public class JDBCBatch {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
connection = DBUtil.getConnection();
statement = connection.createStatement();
long start =new Date().getTime();
System.out.println("开始前:"+start);
for (int i = 0; i < 10000; i++) {
String sql="INSERT INTO userinfo "
+ "VALUES "
+ "(seq_userinfo_id.NEXTVAL,'test"+i+"','123456',"
+ "5000,'test"+i+"@tedu.cn')";
//立刻将SQL发送至数据库服务端
statement.executeUpdate(sql);
}
System.out.println("结束用时:"+(new Date().getTime()-start));
} catch (Exception e) {
}finally {
DBUtil.closeConnection();
}
}
}
输出:
开始前:1502871180710
结束用时:10757
不自动提交:
public class JDBCDemo2 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement pStatement;
try {
connection = DBUtil.getConnection();
connection.setAutoCommit(false);
String sql="INSERT INTO userinfo "
+ "VALUES "
+ "(seq_userinfo_id.NEXTVAL,?,'123456',5000"
+ ",?)";
pStatement = connection.prepareStatement(sql);
long time = new Date().getTime();
for (int i = 0; i < 10000; i++) {
pStatement.setString(1, "aa"+i);
pStatement.setString(2, "scu@qq.com"+i);
pStatement.addBatch();
}
pStatement.executeBatch();
System.out.println("用时:"+(new Date().getTime() - time));
//清空本地缓存
pStatement.clearBatch();
connection.commit();
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
DBUtil.closeConnection();
}
}
}
输出:
用时:103
public class BatchInsertDemo {
public static void main(String[] args) throws SQLException {
Connection connection = JDBCUtils.getConnection();
connection.setAutoCommit(false);
PreparedStatement preparedStatement = connection.prepareStatement("insert into users(username) values(?)");
for(int i = 0; i < 10000; i++)
{
preparedStatement.setString(1,"张"+i);
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
connection.commit();
System.out.println("插入完成");
}
}