传智播客李勇Jdbc视频笔记(18-25)

18、完成整个DAO的实现及测试代码
public class DaoFactory {
//这句代码一定要放到构造DaoFactory()对象之前,否则在构造完成之后给userDao原本已经
//赋值完成 现在又要变成null了
private UserDao userDao = null;
private static DaoFactory instance = new DaoFactory();
private DaoFactory() {
try {
Properties props = new Properties();
InputStream in = DaoFactory.class.getClassLoader().
getResourceAsStream("daoconfig.properties");
//用下面的方式来构建一个输入流也是 可以的,但是你会发现我们的路径都是写死的,如果我们的配置文件
//改变了地方,就找不到文件了 而如果我们用上面类加载器的方法来得到一个文件的输入流,只要这个文件在
//classpath路径下面就能找到他
//InputStream in = new FileInputStream("src/daoconfig.properties");
props.load(in);
in.close();
String className = props.getProperty("className");
Class clazz = Class.forName(className);
userDao = (UserDao) clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
throw new ExceptionInInitializerError(e.getMessage());
}
}

public static DaoFactory getInstance() {
return instance;
}

public UserDao getUserDao() {
return userDao;
}
}


19、事务的概念与JDBC事务处理
(1)原子性(atomicity):组成事务处理的语句形成了一个逻辑单元,不能只执行其中的一部分。
(2)一致性(consistency):在事务处理执行前后,数据库是一致的(两个账户要么都变,或者都不变)。
(3)隔离性(isolcation):一个事务处理对另一个事务处理没有影响。
(4)持续性(durability):事务处理的效果能够被永久保存下来 。
举例:银行转账
connection.setAutoCommit(false);//打开事务。
.....
....把进行转账的两步操作放在同一个事务中,如果一个出现异常,马上回滚
.....
connection.commit();//提交事务。
connection.rollback();//回滚事务。

20、事务的保存点处理:定义保存点可以用来回滚一部分内容
static void test() throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
//定义保存点
Savepoint sp = null;
try {
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false);
st = conn.createStatement();
//修改张三的money值
String sql = "update user set money=money-10 where id=1";
st.executeUpdate(sql);
//设置保存点
sp = conn.setSavepoint();

//修改王五的money值
sql = "update user set money=money-10 where id=3";
st.executeUpdate(sql);

sql = "select money from user where id=2";
rs = st.executeQuery(sql);
float money = 0.0f;
if (rs.next()) {
money = rs.getFloat("money");
}
//如果李四的money的值>300就抛出异常
if (money > 300)
throw new RuntimeException("已经超过最大值!");
sql = "update user set money=money+10 where id=2";
st.executeUpdate(sql);

conn.commit();
} catch (RuntimeException e) {
if (conn != null && sp != null) {
//rollback的时候要定义保存点,否则会全部回滚
conn.rollback(sp);
conn.commit();
}
throw e;
} catch (SQLException e) {
if (conn != null)
conn.rollback();
throw e;
} finally {
JdbcUtils.free(rs, st, conn);
}
}

总结:如果上面的调用产生了异常,那么张三账号的会减少,而王五的钱不会变少:保存点之后的内容会被回滚
而保存点之前的内容不会被回滚。

22、JTA分布式事务的简要介绍
跨越多个数据源的事务,使用JTA容器实现事务。
分成两阶段提交。
javax.transaction.UserTransaction tx = (UserTransaction)ctx.lookup(“jndiName");
tx.begin();
//connection1 connection2 (可能来自不同的数据库)…
tx.commit();//tx.rollback();


23、事务的隔离级别

[img]http://dl.iteye.com/upload/attachment/229133/25b00d3b-8f0d-3b68-a049-84e02f852649.jpg[/img]

查看与设置mysql数据库的的隔离级别:
查看:select @@tx_isolation
未提交读:set transaction isolation level read uncommitted
提交读:set transaction isolation level read committed
不可重复读:set transaction isolation level repeatable committed

在默认情况下mysql的事务是自动提交的,输入命令strat transaction 表示你要
自己手动控制事务,mysql不会帮你自动提交事务 commit命令是提交当前事务
rollback:回滚事务

24、使用JDBC调用存储过程
(1)下面是在mysql客户端工具 Mysql query Brower 中创建的一个存储过程,模拟添加用户
DELIMITER $$

DROP PROCEDURE IF EXISTS `jdbc`.`addUser` $$
CREATE PROCEDURE `jdbc`.`addUser` (in name varchar(45), in sex varchar(10), out pid int)
BEGIN
insert into user(name, sex) values(name, sex);
select last_insert_id() into pid;
END $$

DELIMITER ;

//在`addUser` (in name varchar(45), in sex varchar(10), out pid int)中
//in:表示输入参数 out:表示输出参数
//last_insert_id()是mysql所特有的一个函数,可以查询出最后一次插入到数据库的那条数据的id


(2)java客户端对于存储过程的调用

public static void CallableStatementTest() throws Exception {
Connection conn = JdbcUtils.getConnection();
// call :是固定写法, addUser 是我们在数据库中定义的存储过程的名字后面指定参数
//如果没有任何参数 addUser后的括号也要写上
String sql = "{call addUser(?,?,?)}";
CallableStatement cs = conn.prepareCall(sql);
//注册一个输出参数并知名类型 第一参数指的是sql中三个问号中规定返回值的那个问号
//这个要与存储过程中所定义的顺序一样。
cs.registerOutParameter(3, Types.INTEGER);
cs.setString(1, "zhangsan");
cs.setString(2, "男");
cs.executeUpdate();

int id = cs.getInt(3);
System.out.println(id);
}


下面的示例是返回当前这条记录插入后形成的id

public static void returnId() throws Exception{
Connection conn = JdbcUtils.getConnection();
String sql = "insert into user(name, sex) values (?,?)";
//虽然说第二个参数不写可能也能返回,但是这和不同的数据库产品以及相应的驱动有关
//所以这个参数最好还是要写上
PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
pstmt.setString(1, "lisi");
pstmt.setString(2, "女");

pstmt.executeUpdate();
//getGeneratedKeys()这个方法为什么不是返回int类型而是要返回一个ResultSet类型呢?因为他考虑到了联合主键
//的问题,有可能是一张表中的几个字段合起来构成一个id,这样就不能返回一个int类型了,如果是联合主键返回的是
//多列的内容,我们可以遍历ResultSet得到联合主键列的值
ResultSet rs = pstmt.getGeneratedKeys();
int id = 0;
if(rs.next()) {
id = rs.getInt(1);
}
System.out.println(id + "===");
JdbcUtils.free(rs, pstmt, conn);
}


25、使用JDBC的批处理功能
//main方法调用测试批量插入与普通的insert所消耗的时间比
public static void main(String[] args) throws SQLException {
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++)
create(i);
long end = System.currentTimeMillis();
System.out.println("create:" + (end - start));

start = System.currentTimeMillis();
createBatch();
end = System.currentTimeMillis();
System.out.println("createBatch:" + (end - start));
}
//普通方法
static void create(int i) throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "insert into user(name,birthday, money) values (?, ?, ?) ";
ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, "no batch name" + i);
ps.setDate(2, new Date(System.currentTimeMillis()));
ps.setFloat(3, 100f + i);

ps.executeUpdate();
} finally {
JdbcUtils.free(rs, ps, conn);
}
}
//批量插入数据
static void createBatch() throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
String sql = "insert into user(name,birthday, money) values (?, ?, ?) ";
ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
//每循环一次都会形成一条新的sql语句被打包,直到循环完成然后进行批量的处理
//那么可不可以无限量的增加呢?其实会产生内存溢出的情况,到底循环多少次进行打包才合适
//这个值要经过测试
for (int i = 0; i < 100; i++) {
ps.setString(1, "batch name" + i);
ps.setDate(2, new Date(System.currentTimeMillis()));
ps.setFloat(3, 100f + i);

ps.addBatch();
}
int[] is = ps.executeBatch();
} finally {
JdbcUtils.free(rs, ps, conn);
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值