千峰JAVA逆战班Day40

Day40

*对执行DQL的方法进行封装

​ I. 连接,设置参数等方式跟封装DML是一样的,但是DQL返回的是一个结果集,所以需要对这个结果集进行处理。那么怎么处理呢?自然是封装到一个集合当中进行返回。首先,我们肯定是需要自定义一个实体类来保存这些信息(实体类的属性名必须保证和sql语句的字段别名一致),那么我就等于是知道了这个集合的类型,如果要将类型告知给方法,那么自然是要使用Class对象作为参数传入,而且类型和返回的集合类型一致,这样我们就可以使用泛型来进行一个限制。

public static <T> List<T> executeDQL(Class<T> cls , String sql,Object...params){}

​ II. 参数,返回值定好了之后,自然是要进行逻辑代码的实现,也就是将结果集保存到list集合中

//·连接代码略,ps是预处理对象,rs是结果集
//·保存实体类对象的集合
List<T> list = new ArrayList<T>();
//·获取查询结果的元数据
ResultSetMetaData rm = ps.getMetaData();
T t;
while(rs.next()) {
	//·获取一个实体类对象
	t = cls.newInstance();
	//·getColumnCount()可以获取到有多少个字段	
	for (int i = 1; i <= rm.getColumnCount(); i++) {
		//·通过元数据获取字段的别名
		String name = rm.getColumnLabel(i);
		
		//·通过反射、属性名获取到这个对象的属性
		Field field = cls.getDeclaredField(name);
        //·打开权限(因为是私有属性)
		field.setAccessible(true);
        //·通过别名获取结果集的数据
		Object value = rs.getObject(name);
        //·对实体类的对象的属性进行复制
		field.set(t, value);
    	}
    //·将实体类添加进集合
	list.add(t);
}
return list;

​ III. 优化:这样写是有两个小bug的,①实体类里面肯定不会存在外键,但是数据库的查询结果集可能存在外键;②如果数据库里的数据不完整(比如有空值,且恰好是数字类型的值为null),则在对实体类属性的赋值上会有一定的问题(数字类型没法赋值为null)。

​ 1)使用try catch 处理第一个bug,抓住异常不做处理,因为对于实体类来说外键是废数据,可以直接忽略

try {
    //·这里可能会出现异常:实体类里面没有数据库的外键
	Field field = cls.getDeclaredField(name);
	field.setAccessible(true);
	Object value = rs.getObject(name);
	field.set(t, value);
	} catch (NoSuchFieldException e) {
	}

​ 2)加一个空值判断解决第二个bug,这里使用了continue直接跳过赋值,因为如果不赋值,那么成员会自动使用默认值,而数据库中的null在没有设置默认值的情况下也恰好代表这个意思。

Object value = rs.getObject(name);
//·如果是数字类型为空,直接赋值会有问题
if(value == null) {
continue;
}
field.set(t, value);

至此,一个基础版的DQL封装就完成了

*基于BaseDao开发和项目包结构

在这里插入图片描述

在这里插入图片描述

*面向接口开发

在这里插入图片描述

*事务

​ I. 概念:保证一组sql语句能够同时成功或者同时失败,且不会被其它事务所影响。

​ II. 事务的ACID:

Atomicity(原子性)表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败
Consistency(一致性)表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态.事务执行前和执行后来源和去向保持平衡。
Isolation(隔离性)事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。并发时每个事务是隔离的,相互不影响。
Durability(持久性)持久性事务完成之后,它对于系统的影响是永久性的。

​ III. java代码中实现事务

try{
    Connection.setAutoCommit(false);//·关闭了自动提交事务
	//·加入几条sql语句
    Connection.commit();//所有sql语句正常执行完毕 则提交
}catch(Exception e){
    System.out.println("发生了异常");
    Connection.rollback();//·如果发生异常就进行回归
}

​ IV. 事务的隔离级别

​ 1)read uncommitted 未提交读(可能会发生脏读,不可重复读,虚读)

​ 2)read committed 提交读(可能会发生不可重复读,虚读)

​ 3)repeatable 重复读(可能会发生虚读)

​ 4)Serializable 可串行化(都避免了,但是资源消耗很大)

​ V. 脏读,不可重复读,可重复读,虚读

​ 1)脏读:事务1修改了一个值,但是还未提交;此时事务2对这个数据进行读取,读取到了修改后的值。

​ 2)不可重复读:事务1第一次查询了一个数据发现是200,在事务1还没提交时,事务2将这个数据修改成了100并提交,事务1又查询了一次,发现值变成了100.

​ 3)可重复读:与上面的情况相同,但是事务1又查询时,值还是200,直到事务1提交之后,重新开了一个事务3再查询时,值才会变成100.

​ 4)虚读:与上面情况相同,但是事务2不再是修改数据,而是添加了一条新数据,当事务1又查询一次时,发现多了一条新数据.

的情况相同,但是事务1又查询时,值还是200,直到事务1提交之后,重新开了一个事务3再查询时,值才会变成100.

​ 4)虚读:与上面情况相同,但是事务2不再是修改数据,而是添加了一条新数据,当事务1又查询一次时,发现多了一条新数据.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值