一、JDBC是什么?
JDBC(Java database connectivity)数据库连接。是Java语言中用来规范客户端程序如何来访问数据库[关系型数据库]应用程序接口,提供了诸如查询和跟新数据库中数据的方法。
我们通常说的JDBC是面向关系型数据库的。
二、JDBC访问数据库需要用到的类、接口、方法?
2.1Java.sql包DriverManager类–负责加载各种不同驱动程序(Driver),并根据不同的请求,向调用者返回相应的数据库连接。驱动程序,会将自身加载到DriverManager中去。
2.1.1数据库驱动程序(Driver)–根据所连接的数据库不同需要下载对应数据库的驱动程序。
例如:mysql数据库—MySQL :: Download MySQL Connector/J (Archived Versions)
mysql-connection-java-5.1.38-bin.jar
通过Java的反射机制来给DriverManager,提供加载的数据库驱动名称。
Class.forName(“数据库驱动名称【包名+类名】”);
数据库驱动名称来自mysql-connection-java5.1.38-bin.jar中Driver的Java类的全名称。
Class.forName(“com.mysql.jdbc.Deiver”);
2.1.2向调用者返回相应的数据库连接
DriverManager类中的静态方法getConnection(URL,username,password)向调用者返回相应的数据库连接
参数 url–指定被连接数据库位置【jdbc:mysql://数据库服务器:IP地址:端口号/数据库名称】
参数 username—登录数据库的用户名
参数 password–登录数据库的密码
2.2java.sql包Connection接口–数据库连接,负责与进行数据库间通讯,sql执行以及事务处理都是某个特定Connection环境中进行的。可以产生要了国内与执行sql的Statement。
1.产生用于执行的sql的Statement
[用以执行包含动态参数的SQL查询和更新(针对静态sql语句和单词执行)]
Staement createStatement()
select * from t_user where uid=12;
2.产生用以执行sql的PreparedStatement.
[用以执行包含动态参数的sql查询和更新(在服务器端编译,允许重复执行以提高效率)] PreparedStatement prepartatement(sql);
参数sql—包含动态参数的sql语句
select * from t_user where uid=?;【需要给sql动态传递参数】
?—占位符
2.3java.sql包Statement接口–用以执行sql查询和更新(针对静态sql语句和单词执行)
以执行sql更新【insert/update/delete】
int executeUpdate()
以执行sql查询【select】
ReselutSet executeQuery(sql);
参数SQL—[select]字符串类型的sql语句。
2.4java.sql包PreparedStatement接口–用于以执行包含动态参数的sql查询和更新(在服务器端编译,允许重复执行以提高效率)
以执行sql更新【insert/update/delete】
int executeUpdate( )
以执行sql查询【select】
ResultSet executeQuery()
注意:PreparedStatement需要执行的sql语句
1.sql语句实在创建PreparedStatement对象的时候传入执行,不是在调用executeUpdate()/executeQuery()的时候传入。
2.preparedStatement对象所执行的sql语句中有“?”【占位符】
有一组补充sql语句占位符的方法
setInt(参数1,参数2) int–int
setLong(参数1,参数2) long—bigint
setDouble(参数1,参数2) double–double
setString(参数1,参数2) String–varchar/char
…………………
参数1—SQL语句中“?”的位置【从1开始】
参数2—SQL语句中“?”具体数据值
2.5Java.sql包ResultSet接口—数据库结果集的数据表,通常通过执行查询数据库的语句生成
ResulSet对象具有指向其当前数据行的指针。最初,指针被置于第一行之间。next方法将指针移动到下一行,因为该方法在ResultSet对象中没有下一行时返回false,所以可以在while询函中使用它来迭代结果集。
默认的ResultSet独享不可更新。仅有一个向前移动的指针。因此,只能迭代它一次,并且只能从能按从第一行到做后一行的顺序进行。
boolean next()—将指针移动到下一行;因为该方法在ResulSet对象中没有下一行时返回false。在while循环中使用它来迭代结果集。
由于通过next方法将指针移动到下一行,我们现在就可以取出指针指向的当前行的数据值。要获取当前行中保存的数据值,就需要一列一列的取出数据值,所以ResulSet会有一组获取指定列数据的方法。
getxxxx(int colindex)—-int colindex[当前需要获取数据值的列在当前行的位置【从0开始】]
getxxxx(string colname)—String colname[当前需要获取数据值的列名]
1 [int]–[id]
Zhangsan [varchar]–[name]
23 [int]–[age]
2[int]–[id]
Lisi [varchar]–[name]
24 [int]–[age]
3[int]–[id]
Wangwu [varchar]–[name]
25 [int]–[age]
通过ResultSet对象得到第一行数据值
int id=ResultSet对象.getInt(0);
int id=ResultSet对象.getInt(“id”);
//id==1
String name=ResultSet对象.getString(1);
String name=ResultSet对象.getString(“name”);
//name==zhangsan
int age=ResultSet对象.getInt(2);
int age=ResultSet对象.getInt(“age”);
//age==23
三、 访问数据库的流程
测试基于Statement接口的数据库测试
1.创建数据库表t_user
create table t_user(
user_id int primary key auto_increment,
user_name varchar(22),
user_pass varchar(22),
user_age int,
user_sex boolean,
user_hei double
);
2、创建java项目,导入数据库启动包
3.创建保存用户信息的用户类package com.wangixng.test1; /** * 保存用户信息的java类 * @author Administrator * */ public class userBean { private int userid; private String username; private String userpass; private int userage; private boolean usersex; private double userhei; public userBean(){} public userBean(int userid,String username,String userpass,int userage,boolean usersex,double userhei){ this.userid=userid; this.username=username; this.userpass=userpass; this.userage=userage; this.usersex=usersex; this.userhei=userhei; } public int getUserid() { return userid; } public void setUserid(int userid) { this.userid = userid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getUserpass() { return userpass; } public void setUserpass(String userpass) { this.userpass = userpass; } public int getUserage() { return userage; } public void setUserage(int userage) { this.userage = userage; } public boolean isUsersex() { return usersex; } public void setUsersex(boolean usersex) { this.usersex = usersex; } public double getUserhei() { return userhei; } public void setUserhei(double userhei) { this.userhei = userhei; } }
4.创建数据库驱动管理类
package com.wangixng.test1; /* * 数据库驱动管理类--加载数据库启动,得到数据库连接 * @author 联想 * */ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBconnection { //定义数据库驱动名称 private static final String DRIVERNAME="com.mysql.jdbc.Driver"; //定义数据库的url private static final String URL="jdbc:mysql://127.0.0.1:3306/test"; //定义数据库的登录名 private static final String USERNAME="root"; //定义数据库的密码 private static final String PASSWORD="123456"; //加载数据库驱动 static{ try { Class.forName(DRIVERNAME); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //得到数据库连接对象方法 public static Connection getMyConnection(){ //创建保存数据库连接对象 Connection connection=null; try { connection=DriverManager.getConnection(URL, USERNAME, PASSWORD); System.out.println(connection); } catch (SQLException e) { System.out.println("连接数据库败!"); e.printStackTrace(); } return connection; } }
5.创建数据用户表信息的访问类
package com.wangixng.test1; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; /* * 用户数据库表的访问对象 */ public class userService { // 添加用户信息 public void insetUser(userBean userBean) { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句的Statement对象 Statement statement = null; // 得到数据库连接对象 conn = DBconnection.getMyConnection(); // 创建添加数据的sql语句 String inset = "insert into t_user values(null,'" + userBean.getUsername() + "','" + userBean.getUserpass() + "'," + userBean.getUserage() + "," + userBean.isUsersex() + "," + userBean.getUserhei() + ");"; System.out.println(inset); try { // 创建Statement对象使用sql语句 statement = conn.createStatement(); // 执行添加sql语句 int temp = statement.executeUpdate(inset); if (temp > 0) { System.out.println("添加成功!"); } } catch (SQLException e) { System.out.println("添加失败!"); e.printStackTrace(); } finally { if (statement != null && conn != null) { try { statement.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } // 查询所有用户信息 public ArrayList<userBean> selectALLUser() { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句的Statement对象 Statement statement = null; // 创建保存实现数据库指针的ResultSet接口对象 ResultSet resultSet = null; // 创建一个保存从数据库得到信息的集合 ArrayList<userBean> userlist = new ArrayList(); // 得到数据库连接对象 conn = DBconnection.getMyConnection(); // 创建添加数据的sql语句 String selectAll = "select * from t_user"; System.out.println(selectAll); try { // 创建Statement对象使用sql语句 statement = conn.createStatement(); // 执行添加sql语句 resultSet = statement.executeQuery(selectAll); // 使用ResultSet接口的next()方法一行一行找记录 while (resultSet.next()) { int userid = resultSet.getInt("user_id"); String username = resultSet.getString("user_name"); String useruserpass = resultSet.getString("user_pass"); int userage = resultSet.getInt("user_age"); boolean usersex = resultSet.getBoolean("user_sex"); double userhei = resultSet.getDouble("user_hei"); userBean userBean = new userBean(); userBean.setUserid(userid); userBean.setUsername(username); userBean.setUserpass(useruserpass); userBean.setUserage(userage); userBean.setUsersex(usersex); userBean.setUserhei(userhei); userlist.add(userBean); } } catch (SQLException e) { System.out.println("查询失败!"); e.printStackTrace(); } finally { if (statement != null && conn != null && resultSet != null) { try { resultSet.close(); statement.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return userlist; } // 根据ID查询用户信息 public userBean selectAUser(int id) { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句的Statement对象 Statement statement = null; // 创建保存实现数据库指针的ResultSet接口对象 ResultSet resultSet = null; // 创建一个保存userBean对象 userBean userBean = null; // 得到数据库连接对象 conn = DBconnection.getMyConnection(); // 创建添加数据的sql语句 String selectA = "select * from t_user where user_id=" + id + ";"; System.out.println(selectA); try { // 创建Statement对象使用sql语句 statement = conn.createStatement(); // 执行添加sql语句 resultSet = statement.executeQuery(selectA); // 使用ResultSet接口的next()方法一行一行找记录 while (resultSet.next()) { int userid = resultSet.getInt("user_id"); String username = resultSet.getString("user_name"); String useruserpass = resultSet.getString("user_pass"); int userage = resultSet.getInt("user_age"); boolean usersex = resultSet.getBoolean("user_sex"); double userhei = resultSet.getDouble("user_hei"); userBean = new userBean(); userBean.setUserid(userid); userBean.setUsername(username); userBean.setUserpass(useruserpass); userBean.setUserage(userage); userBean.setUsersex(usersex); userBean.setUserhei(userhei); } } catch (SQLException e) { System.out.println("查询此ID用户信息失败!"); e.printStackTrace(); } finally { if (statement != null && conn != null && resultSet != null) { try { resultSet.close(); statement.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return userBean; } // 根据ID修改用户信息 public void updatetAUser(userBean userBean) { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句的Statement对象 Statement statement = null; // 得到数据库连接对象 conn = DBconnection.getMyConnection(); // 创建添加数据的sql语句 String updateA = "update t_user set user_name='" + userBean.getUsername() + "',user_pass='" + userBean.getUserpass() + "',user_age=" + userBean.getUserage() +",user_sex="+userBean.isUsersex() +",user_hei="+userBean.getUserhei()+ "where user_id=" + userBean.getUserid()+ ";"; System.out.println(updateA); try { // 创建Statement对象使用sql语句 statement = conn.createStatement(); // 执行添加sql语句 int temp= statement.executeUpdate(updateA); // 使用ResultSet接口的next()方法一行一行找记录 if(temp>0){ System.out.println("修改成功!"); } } catch (SQLException e) { System.out.println("修改失败!"); e.printStackTrace(); } finally { if (statement != null && conn != null) { try { statement.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } // 根据ID删除用户信息 public void deletA(int id){ //创建保存连接数据库的对象 Connection connection=null; //创建保存执行sql语句的Statement对象 Statement statement=null; // 得到数据库连接对象 connection=DBconnection.getMyConnection(); //创建执行的sql语句 String delect="delete from t_user where user_id="+id; try { //创建Statement对象 statement=connection.createStatement(); //执行sql语句 int temp=statement.executeUpdate(delect); if (temp>0) { System.out.println("删除成功!"); } } catch (SQLException e) { System.out.println("删除失败!"); e.printStackTrace(); }finally { if(statement!=null && connection!=null){ try { statement.close(); connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
6.测试
package com.wangixng.test1; public class test1 { public static void main(String[] args) { userBean userBean = new userBean(3, "王五", "135498", 22, true, 175); userService userservice = new userService(); // 给数据库添加信息 userservice.insetUser(userBean); // 测试查询所有用户信息 /* * ArrayList<userBean> userlist=userservice.selectALLUser(); if * (userlist!=null) { System.out.println("正在查询!"); for(userBean * userinfo:userlist){ * System.out.println(userinfo.getUsername()+"\t"+userinfo.getUserhei()) * ; } }else{ System.out.println("无数据!"); } */ // 测试根据ID查询用户信息 /* * userBean userBean2=userservice.selectAUser(2); if(userBean2!=null){ * System.out.println(userBean2.getUsername()+"\t"+userBean2.getUserhei( * )); }else { System.out.println("无数据!"); } */ // 测试根据ID修改用户信息 /*userBean userBean3 = new userBean(2, "王五", "135498", 22, true, 175); userservice.updatetAUser(userBean3);*/ //测试删除用户信息 //userservice.deletA(2); } }
测试基于PreparedStatement接口的数据库访问
1.创建数据库表
create table t_user{
user_id int primary key auto_increment,
user_name varchar(22),
user_pass varchar(22),
user_age int,
user_sex boolean,
user_hei double
}
2.创建java项目,导入数据库驱动包
3.依据数据库表创建保存用户信息的java类(同上)
4.创建数据库连接类(同上)
5.创建数据库连接对象类(同上)
6.创建数据库访问类package com.wangixng.test2; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; /* * 用户数据库表的访问对象 */ public class userService { // 添加用户信息 public void insetUser(userBean userBean) { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句的Statement对象 PreparedStatement pstatement = null; // 得到数据库连接对象 conn = DBconnection.getMyConnection(); try { //创建prepareStatementStatement对象使用sql语句 String insert= "insert into t_user values(?,?,?,?,?,?);"; pstatement=conn.prepareStatement(insert); // 创建添加数据的sql语句 pstatement.setInt(1, userBean.getUserid()); pstatement.setString(2, userBean.getUsername()); pstatement.setString(3, userBean.getUserpass()); pstatement.setInt(4, userBean.getUserage()); pstatement.setBoolean(5, userBean.isUsersex()); pstatement.setDouble(6, userBean.getUserhei()); // 执行添加sql语句 int temp = pstatement.executeUpdate(); if (temp > 0) { System.out.println("添加成功!"); } } catch (SQLException e) { System.out.println("添加失败!"); e.printStackTrace(); } finally { if (pstatement != null && conn != null) { try { pstatement.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } // 查询所有用户信息 public ArrayList<userBean> selectALLUser() { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句的Statement对象 Statement statement = null; // 创建保存实现数据库指针的ResultSet接口对象 ResultSet resultSet = null; // 创建一个保存从数据库得到信息的集合 ArrayList<userBean> userlist = new ArrayList(); // 得到数据库连接对象 conn = DBconnection.getMyConnection(); // 创建添加数据的sql语句 String selectAll = "select * from t_user"; System.out.println(selectAll); try { // 创建Statement对象使用sql语句 statement = conn.createStatement(); // 执行添加sql语句 resultSet = statement.executeQuery(selectAll); // 使用ResultSet接口的next()方法一行一行找记录 while (resultSet.next()) { int userid = resultSet.getInt("user_id"); String username = resultSet.getString("user_name"); String useruserpass = resultSet.getString("user_pass"); int userage = resultSet.getInt("user_age"); boolean usersex = resultSet.getBoolean("user_sex"); double userhei = resultSet.getDouble("user_hei"); userBean userBean = new userBean(); userBean.setUserid(userid); userBean.setUsername(username); userBean.setUserpass(useruserpass); userBean.setUserage(userage); userBean.setUsersex(usersex); userBean.setUserhei(userhei); userlist.add(userBean); } } catch (SQLException e) { System.out.println("查询失败!"); e.printStackTrace(); } finally { if (statement != null && conn != null && resultSet != null) { try { resultSet.close(); statement.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return userlist; } // 根据ID查询用户信息 public userBean selectAUser(int id) { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句的Statement对象 PreparedStatement pstatement = null; // 创建保存实现数据库指针的ResultSet接口对象 ResultSet resultSet = null; // 创建一个保存userBean对象 userBean userBean = null; // 得到数据库连接对象 conn = DBconnection.getMyConnection(); // 创建添加数据的sql语句 try { // 创建Statement对象使用sql语句 String selectA = "select * from t_user where user_id=?;"; System.out.println(selectA); pstatement = conn.prepareStatement(selectA); pstatement.setInt(1, id); // 执行添加sql语句 resultSet = pstatement.executeQuery(); // 使用ResultSet接口的next()方法一行一行找记录 while (resultSet.next()) { int userid = resultSet.getInt("user_id"); String username = resultSet.getString("user_name"); String useruserpass = resultSet.getString("user_pass"); int userage = resultSet.getInt("user_age"); boolean usersex = resultSet.getBoolean("user_sex"); double userhei = resultSet.getDouble("user_hei"); userBean = new userBean(); userBean.setUserid(userid); userBean.setUsername(username); userBean.setUserpass(useruserpass); userBean.setUserage(userage); userBean.setUsersex(usersex); userBean.setUserhei(userhei); } } catch (SQLException e) { System.out.println("查询此ID用户信息失败!"); e.printStackTrace(); } finally { if (pstatement != null && conn != null && resultSet != null) { try { resultSet.close(); pstatement.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return userBean; } // 根据ID修改用户信息 public void updatetAUser(userBean userBean) { // 创建保存数据库连接对象的变量 Connection conn = null; //创建保存执行sql语句的Statement对象 PreparedStatement pstatement = null; // 得到数据库连接对象 conn=DBconnection.getMyConnection(); // 创建添加数据的sql语句 String updateA = "update t_user set user_name=?,user_pass=?,user_age=?,user_sex=?,user_hei=? where user_id=?;"; System.out.println(updateA); try { //创建Statement对象使用sql语句 pstatement = conn.prepareStatement(updateA); pstatement.setString(1, userBean.getUsername()); pstatement.setString(2, userBean.getUserpass()); pstatement.setInt(3, userBean.getUserage()); pstatement.setBoolean(4, userBean.isUsersex()); pstatement.setDouble(5, userBean.getUserhei()); pstatement.setInt(6, userBean.getUserid()); // 执行添加sql语句 int temp= pstatement.executeUpdate(); // 使用ResultSet接口的next()方法一行一行找记录 if(temp>0){ System.out.println("修改成功!"); } } catch (SQLException e) { System.out.println("修改失败!"); e.printStackTrace(); } finally { if (pstatement != null && conn != null) { try { pstatement.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } // 根据ID删除用户信息 public void deletA(int id){ //创建保存连接数据库的对象 Connection connection=null; //创建保存执行sql语句的Statement对象 Statement statement=null; // 得到数据库连接对象 connection=DBconnection.getMyConnection(); //创建执行的sql语句 String delect="delete from t_user where user_id="+id; try { //创建Statement对象 statement=connection.createStatement(); //执行sql语句 int temp=statement.executeUpdate(delect); if (temp>0) { System.out.println("删除成功!"); } } catch (SQLException e) { System.out.println("删除失败!"); e.printStackTrace(); }finally { if(statement!=null && connection!=null){ try { statement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
7.测试
package com.wangixng.test2; import java.util.ArrayList; public class test1 { public static void main(String[] args) { userBean userBean = new userBean(2, "李四", "135498", 22, true, 175); userService userservice = new userService(); // 给数据库添加信息 // userservice.insetUser(userBean); // 测试查询所有用户信息 /*ArrayList<userBean> userlist=userservice.selectALLUser(); if (userlist!=null) { System.out.println("正在查询!"); for(userBean userinfo:userlist){ System.out.println(userinfo.getUsername()+"\t"+userinfo.getUserhei()) ; } }else{ System.out.println("无数据!"); }*/ // 测试根据ID查询用户信息 userBean userBean2=userservice.selectAUser(2); if(userBean2!=null){ System.out.println(userBean2.getUsername()+"\t"+userBean2.getUserhei( )); }else { System.out.println("无数据!"); } // 测试根据ID修改用户信息 /*userBean userBean3 = new userBean(2, "王五", "135498", 22, true, 175); userservice.updatetAUser(userBean3);*/ //测试删除用户信息 //userservice.deletA(2); } }
Statement与PreparedStatement的区别?
Statement接口
PreparedStatement接口
继承关系
是Statement接口的子接口
使用范围
当执行相似SQL(结构相同,具体值不同)语句的次数比较少
当执行相似sql语句的次数比较多(例如用户登陆,对表频繁操作..)语句一样,只是具体的值不一样,被称为动态SQL
优点
语法简单
语句只编译一次,减少编译次数。提高了安全性(阻止了SQL注入)
缺点
采用硬编码效率低,安全性较差。
执行非相似SQL语句时,速度较慢。
原理
硬编码,每次执行时相似SQL都会进行编译
相似SQL只编译一次,减少编译次数
四、什么是事务?
事务(Transaction),一般是指要做的或所做的事情。
在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
程序执行单元(unit)—数据库操作的一组SQL语句的执行。
- 由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写
- 由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
例如:我们要实现一个银行转账的操作,首先从A账户减掉指定的金额,然后B账户增加指定的金额,此时转账操作结束。上面的操作如果对应成数据库操作,那么就需要执行两条update语句。数据库把这两条update语句的执行就是一个事务。
事务–指访问并可能更新数据库中各种数据项的一组SQL语句的执行单元(unit)。
五、数据库的事务的4大特征【ACID】
A.-原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
C–一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
I–隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
D–持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
六、java中事务的隔离级别
在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。
JDBC定义了五种事务隔离级别:
TRANSACTION_READ_UNCOMMITTED 允许脏读、不可重复读和幻读。
TRANSACTION_READ_COMMITTED 禁止脏读,但允许不可重复读和幻读。
TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读,单运行幻读。
TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读。
TRANSACTION_NONE JDBC驱动不支持事务
七、JDBC的事务管理操作
JDBC的事务管理操作需要通过java.sql.Connection接口来设置的。
事务的隔离级别
static int
TRANSACTION_NONE 指示不支持事务的常量。
static int
TRANSACTION_READ_COMMITTED 一个常数表示防止脏读; 可能会发生不可重复的读取和幻像读取。
static int
TRANSACTION_READ_UNCOMMITTED 一个常量表示可能会发生脏读,不可重复读和幻读。
static int
TRANSACTION_REPEATABLE_READ 一个常量表示防止了脏读和不可重复读; 可以发生幻读。
static int
TRANSACTION_SERIALIZABLE 一个常数表示防止脏读,不可重复读和幻影读。
Modifier and Type
Constant Field
Value
public static final int
0
public static final int
2
public static final int
1
public static final int
4
public static final int
8
设置事务隔离级别的方法
void
setTransactionIsolation(int level) 尝试将此 Connection对象的事务隔离级别更改为给定的对象。
例如:
Connection接口对象.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Connection接口对象.setTransactionIsolation(8);设置是否自动提交事务方法【默认JDBC事务是自动提交的】
void
setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。
Connection接口对象.setAutoCommit(false) ; 设置为手动提交事务。
事务的提交方法
void
commit() 使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection对象当前持有的任何数据库锁。
事务的回滚方法【异常中执行】
void
rollback() 撤消在当前事务中所做的所有更改,并释放此 Connection对象当前持有的任何数据库锁。
例如:转账
1.创建用户金额信息表create table t_zhanghu
user_name varchar(20),
user_jmoney double
);
insert into t_zhanghu values(null,’张三’,10000)
insert into t_zhanghu values(null,’李四’,10000);
2.创建数据库驱动管理类package com.wangxing.DBconnection; /* * 数据库驱动管理类 */ import java.sql.Connection; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; public class DBconnection { // 创建数据库名称 private static final String DRIVERNAME = "com.mysql.jdbc.Driver"; // 定义数据库的url private static final String URL = "jdbc:mysql://127.0.0.1:3306/test"; // 定义数据库的登录名 private static final String USERNAME = "root"; // 定义数据库的密码 private static final String PASSWORD = "123456"; // 连接数据库名称 static { try { Class.forName(DRIVERNAME); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 创建得到数据库连接对象方法 public static Connection getMyconnection() { Connection connection = null; try { connection = DriverManager.getConnection(URL, USERNAME, PASSWORD); } catch (SQLException e) { System.out.println("连接数据库败!"); e.printStackTrace(); } return connection; } }
3.创建用户信息类
package com.wangxing.Bean; public class userBean { private String username; private double usermoney; public userBean(String username,double usermoney){ this.username=username; this.usermoney=usermoney; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public double getUsermoney() { return usermoney; } public void setUsermoney(double usermoney) { this.usermoney = usermoney; } }
4.创建转账业务类
package com.wangxing.service; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import com.wangxing.Bean.userBean; import com.wangxing.DBconnection.DBconnection; public class transferService { // 创建添加用户新的方法 public static void adduserinfo(userBean userinfo) { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句对象的变量 PreparedStatement ps = null; // 得到数据库连接对象 conn = DBconnection.getMyconnection(); // 创建要执行的数据库sql语句 String sql = "insert into t_zhuanzhang values(?,?);"; try { ps=conn.prepareCall(sql); ps.setString(1, userinfo.getUsername()); ps.setDouble(2, userinfo.getUsermoney()); int temp=ps.executeUpdate(); if(temp>0){ System.out.println("用户存钱成功成功!"); } ps.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } // 创建转账的方法 public static void transfer(userBean userinfo1, userBean userinfo2, int money) { // 创建保存数据库连接对象的变量 Connection conn = null; // 创建保存执行sql语句对象的变量 PreparedStatement ps = null; // 得到数据库连接对象 conn = DBconnection.getMyconnection(); // 创建要执行的数据库sql语句 String sql = "update t_zhuanzhang set user_money=? where user_name=?;"; try { //设置事务隔离级别 conn.setTransactionIsolation(conn.TRANSACTION_SERIALIZABLE); // 创建手动提交事务 conn.setAutoCommit(false); // 创建PreparedStatement对象执行sql语句 ps = conn.prepareStatement(sql); ps.setDouble(1, userinfo1.getUsermoney() - money); ps.setString(2, userinfo1.getUsername()); ps.executeUpdate(); // 提交 conn.commit(); //int a=10/0; ps.setDouble(1, userinfo2.getUsermoney() + money); ps.setString(2, userinfo2.getUsername()); ps.executeUpdate(); conn.commit(); System.out.println("转账成功"); } catch (SQLException e) { e.printStackTrace(); //当事务有异常时回滚 try { conn.rollback(); System.out.println("转账途中错误,即将返回"); } catch (SQLException e1) { e1.printStackTrace(); } }finally { try { ps.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
5.测试
package com.wangxing.main; import com.wangxing.Bean.userBean; import com.wangxing.service.transferService; public class userMain { public static void main(String[] args) { userBean user1=new userBean("张三",10000); userBean user2=new userBean("李四",10000); transferService service=new transferService(); //添加用户信息 //service.adduserinfo(user1); //service.adduserinfo(user2); //执行转账的方法 service.transfer(user1, user2, 1000); } }
总结:
- SQL语句执行的connection与事务设置的connection对象要相同。
- 开始事务conn.setAutoCommit(false);
- 设置事务的隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
- 提交事务conn.commit();
- 设置事务回滚【异常中进行】conn.rollback();
上面我们所操作的事务管理是编码式事务管理,后面我们在学习Spring框架的时候会学习到声明式事务管理。
八. 通过JDBC使用DBCP与C3P0连接池操作和Druid
1.通过JDBC使用C3P0连接池
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。
例如:
1.创建数据库表
create table t_user(
user_id int primary key auto_increment,
user_name varchar(22),
user_pass varchar(22),
user_age int,
user_sex boolean,
user_hei double
);2.创建Java项目,导入依赖包
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.15.jar
mysql-connector-java-5.1.38.jar3.在src下创建c3p0的配置文件【c3p0-config.xml】
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- c3p0的默认配置项 --> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <property name="user">root</property> <property name="password">123456</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">20</property> </default-config> <!-- 定义的数据库配置 --> <named-config name="test"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <property name="user">root</property> <property name="password">123456</property> <property name="initialPoolSize">25</property> <property name="maxPoolSize">200</property> </named-config> </c3p0-config>
4.创建javabean
package com.wangxing.userBean; public class userBean { private int userid; private String username; private String userpass; private int userage; private boolean usersex; private double userhei; public userBean(int userid,String username,String userpass,int userage,boolean usersex,double userhei){ this.userid=userid; this.username=username; this.userpass=userpass; this.userage=userage; this.usersex=usersex; this.userhei=userhei; } public int getUserid() { return userid; } public void setUserid(int userid) { this.userid = userid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getUserpass() { return userpass; } public void setUserpass(String userpass) { this.userpass = userpass; } public int getUserage() { return userage; } public void setUserage(int userage) { this.userage = userage; } public boolean isUsersex() { return usersex; } public void setUsersex(boolean usersex) { this.usersex = usersex; } public double getUserhei() { return userhei; } public void setUserhei(double userhei) { this.userhei = userhei; } }
5.创建数据库访问类
package com.wangxingc3p0Dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import com.mchange.v2.c3p0.ComboPooledDataSource; import com.wangxing.userBean.userBean; public class userDaoClass { //定义保存cp03数据对象 private ComboPooledDataSource datasource=null; //在userDaoClass中加载自定义数据库表配置项得到数据源 public userDaoClass(){ //加载c3p0-config.xml文件中默认的config //初始化数据 datasource = new ComboPooledDataSource(); //初始化数据源,加载的是自定义的数据库配置项 datasource=new ComboPooledDataSource("test"); } public void insertuser(userBean user){ //保存数据库连接对象 Connection conn=null; //保存执行sql语句的对象 PreparedStatement ps=null; try { //得到数据库连接对象 conn=datasource.getConnection(); //创建添加数据的sql语句 String insert ="insert into t_user values(?,?,?,?,?,?);"; //得到执行sql语句的对象 ps=conn.prepareStatement(insert); ps.setInt(1, user.getUserid()); ps.setString(2, user.getUsername()); ps.setString(3, user.getUserpass()); ps.setInt(4, user.getUserage()); ps.setBoolean(5, user.isUsersex()); ps.setDouble(6, user.getUserhei()); //执行sql语句对数据库进行更改 ps.executeUpdate(); System.out.println("添加成功!"); } catch (SQLException e) { System.out.println("添加失败!"); e.printStackTrace(); }finally{ try { conn.close(); ps.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
优点:不用手动编写创建数据库连接对象的操作,因为c3p0的数据库连接池的配置中已经配置初始化成功。提高程序的执行效率。 日后切换数据库的时候不需要修改源代码,只需要修改c3p0的数据库连接池的配置。
2.
通过JDBC使用dbcp连接池数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
例如:
1.创建数据库表(同上)
2.创建java项目导入jar包
【commons-dbcp-1.4.jarcommons-dbutils-1.6.jar
commons-pool-1.6.jar】
3.在src下创建数据库连接配置文件【xxxxxxxx.properties】
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
username=root
password=123456
maxActive=50
maxIdle=20
maxWait=60000
4.创建javabean(同上)
5.创建数据库访问类package com.wangxingc3p0Dao; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import com.wangxing.userBean.userBean; public class userDaoClass { //定义保存dbcp数据对象 private DataSource dataSource=null; //在userDaoClass中加载自定义数据库表配置项得到数据源 public userDaoClass(){ try { //创建将得到流信息加载到Properties的对象 Properties pro=new Properties(); //创建流去加载数据库连接池 InputStream inStream=this.getClass().getResourceAsStream("/mydata.properties"); //把得到DBconnection.properties的流下载到Properties对象中 pro.load(inStream); //用封装好的工厂去创建这个数据源 dataSource=BasicDataSourceFactory.createDataSource(pro); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void insertuser(userBean user){ //保存数据库连接对象 Connection conn=null; //保存执行sql语句的对象 PreparedStatement ps=null; try { //得到数据库连接对象 conn=dataSource.getConnection(); //创建添加数据的sql语句 String insert ="insert into t_user values(?,?,?,?,?,?);"; //得到执行sql语句的对象 ps=conn.prepareStatement(insert); ps.setInt(1, user.getUserid()); ps.setString(2, user.getUsername()); ps.setString(3, user.getUserpass()); ps.setInt(4, user.getUserage()); ps.setBoolean(5, user.isUsersex()); ps.setDouble(6, user.getUserhei()); //执行sql语句对数据库进行更改 ps.executeUpdate(); System.out.println("添加成功!"); } catch (Exception e) { System.out.println("添加失败!"); e.printStackTrace(); }finally{ try { conn.close(); ps.close(); } catch (Exception e) { e.printStackTrace(); } } } }
3.JDBC访问Druid
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。Druid是阿里巴巴开发的号称为监控而生的数据库连接池!
同时Druid不仅仅是一个数据库连接池,它包括四个部分:
Druid是一个JDBC组件,它包括三个部分:
基于Filter-Chain模式的插件体系。
DruidDataSource 高效可管理的数据库连接池。
SQLParser
Druid的功能
1、替换DBCP和C3P0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
2、可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。
3、数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持PasswordCallback。|
4、SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。
5、扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。
所以Druid可以:
1、充当数据库连接池。
2、可以监控数据库访问性能
3、获得SQL执行日志
例如:
1.创建数据库表
2.创建java项目,导入jar包【druid-1.1.10.jar】
3.在src下创建数据库连接配置文件【xxxxxxxx.properties】
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8
username=root
password=123456
initialSize=100
maxActive=300
maxWait=60000
Druid配置详解https://blog.csdn.net/zhangjinwei417/article/details/92823438
4.创建javabean(同上)
5.创建数据库访问类package com.wangxingc3p0Dao; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Properties; import javax.sql.DataSource; import com.alibaba.druid.pool.DruidDataSourceFactory; import com.wangxing.userBean.userBean; public class userDaoClass { //定义保存dbcp数据对象 private DataSource dataSource=null; //在userDaoClass中加载自定义数据库表配置项得到数据源 public userDaoClass(){ try { Properties pro=new Properties(); InputStream inStream=this.getClass().getResourceAsStream("/mydata.properties"); pro.load(inStream); dataSource=DruidDataSourceFactory.createDataSource(pro); }catch(Exception e) { e.printStackTrace(); } } public void insertuser(userBean user){ //保存数据库连接对象 Connection conn=null; //保存执行sql语句的对象 PreparedStatement ps=null; try { //得到数据库连接对象 conn=dataSource.getConnection(); //创建添加数据的sql语句 String insert ="insert into t_user values(?,?,?,?,?,?);"; //得到执行sql语句的对象 ps=conn.prepareStatement(insert); ps.setInt(1, user.getUserid()); ps.setString(2, user.getUsername()); ps.setString(3, user.getUserpass()); ps.setInt(4, user.getUserage()); ps.setBoolean(5, user.isUsersex()); ps.setDouble(6, user.getUserhei()); //执行sql语句对数据库进行更改 int temp=ps.executeUpdate(); if(temp>0){ System.out.println("添加成功!"); } } catch (Exception e) { System.out.println("添加失败!"); e.printStackTrace(); }finally{ try { ps.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } } }
6.测试
package com.wangxing.main; import com.wangxing.userBean.userBean; import com.wangxingc3p0Dao.userDaoClass; public class userMain { public static void main(String[] args) { userBean user=new userBean(4, "赵六","123456",22,true, 180); userDaoClass userDao=new userDaoClass(); userDao.insertuser(user); } }
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/79830.html