这是数据库中学习的最清楚的一个小章节了,前面的内容还没有补上,在全程班开始的这几天的空挡争取补上,加油,大家都有了自己的目标,学的太晚,加油
批处理
插入大量的数据的时候建议用批处理
statement.addBatch();//添加批处理,先将数据进行缓存
statement.executeBatch();//执行批处理
statement.clearBatch();//清空缓存
调用存储过程 {call [(,, ...)]}
Connection conn = JDBCUtils.getConnection();
String sql="{call testPro(?,?)}"; //输入或输出参数用?占位
CallableStatement prepareCall = conn.prepareCall(sql);
//给输入参数设置值
prepareCall.setInt(1,7369);
//如果有输出参数我们需要注册输出参数
prepareCall.registerOutParameter(2, Types.INTEGER);
boolean b = prepareCall.execute();
//获取输出结果
int r = prepareCall.getInt(2);
System.out.println(r);
//释放资源
JDBCUtils.close(conn,prepareCall);
调用自定义函数 {?=call[( < arg1 >,, ...)]}
String sql="{?=call testFun(?)}";
CallableStatement callableStatement = conn.prepareCall(sql);
//设置输入参数
callableStatement.setInt(2,7902);
//注册返回值
callableStatement.registerOutParameter(1, Types.INTEGER);
callableStatement.execute();
//获取返回的结果
int r = callableStatement.getInt(1);
System.out.println("结果是:"+r);
//释放资源
JDBCUtils.close(conn,callableStatement);
要获取自增长键的值,需要在获取操作对象的时候声明一个参数
Statement.RETURN_GENERATED_KEYS
PreparedStatement preparedStatement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
2.当数据插入成功后,就可以取出这个自增长键的值
//获取自增长键的结果集
ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
while (generatedKeys.next()){
keyValue = generatedKeys.getInt(1);
}
3.你在其他表中就可以使用这个自增长键的值
在一个事务中有多个逻辑单元组成,这些逻辑单元是一个整体,不可分割,要么都成功,要么都失败
案例一:
银行系统,张三给李四进行转钱
解决钱不翼而飞的情况
package org.westos.demo1shiwu;
import org.westos.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @Description:进行转账,出现异常的解决
* @Author:@李小白
* @Date:2019/8/29 10:47
*
* 如果发生了这种钱不翼而飞的异常,我们应该意识到,我们应该把发钱收钱存到一个事务当中。
* 解决:
* 进行手动提交
* 如果发生异常,我们回滚事务
* 不管有没有遇见问题我们都要进行正常提交
* 首先,我们不要抛出异常进行手动抓取,发现关闭资源引用不到向上提取
* 然后我们再进行测试
*
*/
public class JDBCDemo1 {
public static void main(String[] args) {
//张三给李四转钱
Connection conn=null;
PreparedStatement statement1=null;
PreparedStatement statement2=null;
try {
//进行连接数据库
conn = JDBCUtils.getConnection();//默认是自动提交
//进行手动提交
conn.setAutoCommit(false);//设置成手动提交
//张三少钱
String sql1="update bank set money=money-1000 where username='zhangsan'";
statement1 = conn.prepareStatement(sql1);
//执行
statement1.executeUpdate();
//制造错误
//System.out.println(1/0);
//李四多钱
String sql2="update bank set money=money+1000 where username='lisi'";
statement2 = conn.prepareStatement(sql2);
statement2.executeUpdate();
} catch (Exception e) {
//如果遇见问题,我们就进行回滚
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
//不管有无异常我们都进行提交
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
//释放资源
try {
conn.close();
statement1.close();
statement2.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
案例二
银行系统转账,制造回滚点
package org.westos.demo1shiwu;
import org.westos.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;
/**
* @Description:进行转账,设置回滚点
* @Author:@李小白
* @Date:2019/8/29 10:47
*
* 分别两次进行转账
* 第一次转账1000,第二次转账500,分别制造异常,发现只要有一个异常我们都转不过去
* 第一次没有异常第二次遇到异常
* 解决
* 制造回滚点
* 只要出现异常就回到回滚点
*
*/
public class JDBCDemo2 {
public static void main(String[] args) {
//张三给李四转钱
Connection conn=null;
PreparedStatement statement1=null;
PreparedStatement statement2=null;
PreparedStatement statement3=null;
PreparedStatement statement4=null;
Savepoint savepoint=null;
try {
//进行连接数据库
conn = JDBCUtils.getConnection();
//进行手动提交
conn.setAutoCommit(false);
//第一次转账
//张三少钱
String sql1="update bank set money=money-1000 where username='zhangsan'";
statement1 = conn.prepareStatement(sql1);
//执行
statement1.executeUpdate();
//制造异常
// System.out.println(1/0);
//李四多钱
String sql2="update bank set money=money+1000 where username='lisi'";
statement2 = conn.prepareStatement(sql2);
statement2.executeUpdate();
//第二次转账
savepoint = conn.setSavepoint();
//张三少钱
String sql3="update bank set money=money-500 where username='zhangsan'";
statement3 = conn.prepareStatement(sql3);
//执行
statement3.executeUpdate();
//制造异常
System.out.println(1/0);
//李四多钱
String sql4="update bank set money=money+500 where username='lisi'";
statement4 = conn.prepareStatement(sql4);
statement4.executeUpdate();
} catch (Exception e) {
//如果遇见问题,我们就进行回滚
try {
// conn.rollback();//回滚事件
conn.rollback(savepoint);//回滚到指定的回滚点
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
//不管有无异常我们都进行提交
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
//释放资源
try {
conn.close();
statement1.close();
statement2.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
read uncommitted 读未提交 上面的三种情况都会出现
read committed 读已提交 可以避免脏读的情况 Oracle默认级别
repeatable read 可重复度 可避免脏读和不可重复读 MySQL默认级别
serializable 串行化 可以避免所有的问题,,但是效率最低
演示:脏读的发生
zhangsan 给lisi 转钱
开启两个窗口进行演示,一个转钱一个收钱
mysql -uroot -p123456//登录数据库
可以设置数据库的隔离级别,四种隔离级别分别设置
set session transaction isolation level read uncommitted;
开启事务 start transaction;
修改数据:udate bank set money=1500 where username='lisi'
第一种隔离级别
让另一个窗口也开启事务,进行查找数据,查到了就是脏读
zhangsan 一提交commit; lisi又查不到了
第二种隔离级别:
lisi每次查看的钱数都不一样
第三种隔离级别:
lisi需要把卡退出来在进行查询,才能看到
第四种隔离级别:
lisi需要提交再进行查询,才能看到
java中控制隔离级别:(了解)
Connection的api
void setTransactionIsolation(int level)
level是常量
为什么会有连接池?
由于建立数据库资源是一种非常耗时耗资源的行为,在连接池中放一些连接,放在内存中,需要的时候在从连接池中直接申请,借完要还
DataBase Connection Poll数据库连接池
是Apache开发,通过连接池可以自动管理数据库的释放和断开
案例:
转账的硬编码和配置文件编码
BasicDataSource bs = new BasicDataSource();
package org.westos.demo2lianjiechi;
import org.apache.commons.dbcp.BasicDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Description:常见的两种连接池之DBC的硬编码方式
* @Author:@李小白
* @Date:2019/8/30 16:36
* DBCP的硬编码的方式首先导入JAR包
* 然后就是创建数据源,导入Driver的名字和数据库的驱动和用户名和密码
* 然后进行连接数据库,遍历结果集和关闭资源
*
*/
public class DBCPDemo1 {
public static void main(String[] args) throws SQLException {
//依赖DBCP的两个jar包
//创建数据源
BasicDataSource bs = new BasicDataSource();
bs.setDriverClassName("com.mysql.jdbc.Driver");
bs.setUrl("jdbc:mysql://localhost:3306/mydb");
bs.setUsername("root");
bs.setPassword("123456");
bs.setMaxWait(1000);
//进行连接
Connection conn= bs.getConnection();
PreparedStatement statement = conn.prepareStatement("select * from user");
ResultSet resultSet = statement.executeQuery();
//遍历结果集
while (resultSet.next()) {
System.out.println(resultSet.getInt(1));
System.out.println(resultSet.getString(2));
}
//释放资源
conn.close();
bs.close();
statement.close();
resultSet.close();
}
}
配置文件编码
package org.westos.demo2lianjiechi;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
/**
* @Description:DBPC文件配置
* @Author:@李小白
* @Date:2019/8/30 18:11
*/
public class DBPCDemo2 {
public static void main(String[] args) throws Exception {
//把JDBC配置文件进行导入,和MySQL的驱动进行导入
//建立工厂
Properties properties = new Properties();
properties.load(new FileReader("src/dbcp.properties"));
DataSource dataSource = new BasicDataSourceFactory().createDataSource(properties);
//与数据库进行连接
Connection conn = dataSource.getConnection();
PreparedStatement statement = conn.prepareStatement("select * from user");
ResultSet resultSet = statement.executeQuery();
//进行遍历
while (resultSet.next()) {
System.out.println(resultSet.getInt(1));
System.out.println(resultSet.getString(2));
}
//关闭资源
conn.close();
statement.close();
resultSet.close();
}
}
是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。
package org.westos.demo2lianjiechi;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Description:C3P0硬编代码
* @Author:@李小白
* @Date:2019/8/30 18:25
*/
public class C3P0Demo1 {
public static void main(String[] args) throws PropertyVetoException, SQLException {
//把数据库和C3P0的jar包进导入
//创建数据源
ComboPooledDataSource source = new ComboPooledDataSource();
source.setDriverClass("com.mysql.jdbc.Driver");
source.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");//查询的库名字
source.setUser("root");
source.setPassword("123456");
//和数据库进行连接
Connection conn = source.getConnection();
PreparedStatement statement = conn.prepareStatement("select * from user ");
ResultSet resultSet = statement.executeQuery();
//遍历结果集
while (resultSet.next()) {
System.out.println(resultSet.getInt(1));
System.out.println(resultSet.getString(2));
}
//关闭数据流
conn.close();
statement.close();
resultSet.close();
}
}
配置文件编码
要求1:配置文件的名称:c3p0.properties 或者 c3p0-config.xml
要求2:配置文件的路径:src下编码只需要一句话
new ComboPooledDataSource()//使用默认的配置
//可以切换xml配置文件中的标签 来加载不同的配置比如更换Orecal的数据库的配置
new ComboPooledDataSource(String configName)//使用命名的配置 若配置的名字找不到,使用默认的配置
package org.westos.demo2lianjiechi;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Description:C3p0进行文件配置
* @Author:@李小白
* @Date:2019/8/30 18:45
*/
public class c3p0Demo2 {
public static void main(String[] args) throws SQLException {
//导入C3P0的配置文件jar包和MySQL的驱动JAR包
//方法一:完成了
//方法二:如果使用xml文件的第二配置,就把xml文件第二配置的名称传过来,就完成了
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("MyConfig");
//与数据库进行连接
Connection conn = comboPooledDataSource.getConnection();
PreparedStatement statement = conn.prepareStatement("select * from USER ");
ResultSet resultSet = statement.executeQuery();
//遍历结果集
while (resultSet.next()) {
System.out.println(resultSet.getInt(1));
System.out.println(resultSet.getString(2));
}
//释放资源
conn.close();
statement.close();
resultSet.close();
}
}
Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,
使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
使用步骤:
1.导入jar包(commons-dbutils-1.4.jar)
2.创建一个queryrunner类
queryrunner作用:操作sql语句
构造方法:
new QueryRunner(Datasource ds);
3.编写sql
4.执行sql
query(…):执行r操作
update(…):执行cud操作
使用步骤
// 创建对象
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
// 定义sql
String sql = "insert into bank(username,money) values(?,?)";
// 执行sql
runner.update(sql,"赵六",500);
....
执行查询后返回的结果集
ResultSetHandler:封装结果集 接口
BeanListHandler, 将查询结果的每一条记录封装成指定的bean对象,将每一个bean对象放入list中 返回.
案例
package org.westos.demo2lianjiechi;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import javax.sql.DataSource;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* @Description:DBUtils:简化JDBC封装的开源工具
* @Author:@李小白
* @Date:2019/8/30 20:38
*/
public class DuridDBUtilsDemo1 {
public static void main(String[] args) throws Exception {
//导入DBUtils的JAR包,和数据库的JAR包
//创建德鲁伊的工厂类
Properties properties = new Properties();
properties.load(new FileReader("src/druid.properties"));
DataSource ds = new DruidDataSourceFactory().createDataSource(properties);
//创建QueryRunner 对象
//传入数据源
QueryRunner queryRunner = new QueryRunner(ds);
//DML DQL返回值,你影响的行数
int i = queryRunner.update("insert into user values(?,?)", 4, "李强娜");
if (i>0) {
System.out.println("插入成功");
}else {
System.out.println("插入失败");
}
//把你要查询的数据封装起来,//BeanListHandler,把数据库查出来的多条数据用对象封装气啦,再把对象放到集合里面
List query = queryRunner.query("select * from user", new BeanListHandler(User.class));
System.out.println(query);
//查询一条结果把结果放到对象里面 BeanHandler
User query1 = queryRunner.query("select * from user ", new BeanHandler(User.class));
System.out.println(query1);
//MapHandler () 把查询的结果放到Map集合里面
Map map = queryRunner.query("select * from user ", new MapHandler());
System.out.println(map);
Object id = map.get("id");
System.out.println(id);
Object username = map.get("username");
System.out.println(username);
System.out.println(map.size());
}
}
package org.westos.demo2lianjiechi;
/**
* @Description:TODO
* @Author:@李小白
* @Date:2019/8/30 21:00
*/
public class User {
private int id;
private String name;
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
package org.westos.demo2lianjiechi;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Description:连接池里面的德鲁伊连接池(DRUID),硬编码的方式
* @Author:@李小白
* @Date:2019/8/30 19:12
*/
public class DruidDemo1 {
public static void main(String[] args) throws SQLException {
//德鲁伊连接池和DBCP连接池真的很像
//导入德鲁伊连接池的JAR包和MySQL的jar包
//创建数据源
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql:///mydb");
ds.setUsername("root");
ds.setPassword("123456");
//和数据库建立连接
DruidPooledConnection conn = ds.getConnection();
PreparedStatement statement = conn.prepareStatement("select * from user");
ResultSet resultSet = statement.executeQuery();
//遍历结果集
while (resultSet.next()) {
System.out.println(resultSet.getInt(1));
System.out.println(resultSet.getString(2));
}
//释放资源
conn.close();
statement.close();
resultSet.close();
}
}
package org.westos.demo2lianjiechi;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
/**
* @Description:德鲁伊的调用配置文件
* @Author:@李小白
* @Date:2019/8/30 19:32
*/
public class DruidDemo2 {
public static void main(String[] args) throws Exception {
//导入德鲁伊的配置文件,jar包,MySQL的jar包
//配置文件的方式
Properties properties = new Properties();
properties.load(new FileReader("src/druid.properties"));
//用工厂类,创建一个数据源
DataSource dataSource = new DruidDataSourceFactory().createDataSource(properties);
//开始和数据库进行连接
Connection conn = dataSource.getConnection();
PreparedStatement statement = conn.prepareStatement("select * from user");
ResultSet resultSet = statement.executeQuery();
//遍历结果集
while (resultSet.next()) {
System.out.println(resultSet.getInt(1));
System.out.println(resultSet.getString(2));
}
//释放资源
conn.close();
statement.close();
resultSet.close();
}
}