Hibernate 事务管理 多表操作

Hibernate事务管理:

我们在真正进行事务管理的时候,需要考虑事务的应用场景,也就是说我们的事务控制不应该是在DAO层实现的,应该在Service层实现的,并且在Service中调用多个DAO实现一个业务逻辑的操作。其实最主要的是如何保证在Service中开启事务时使用的Session对象和DAO中多个操作使用的是同一个Session对象。可以有两种方法实现:

  1. 在业务层获取到Session,并将Session作为参数传递给DAO
  2. 使用ThreadLocal将业务层获取的Session绑定到当前线程中,然后在DAO中获取Session时,都从当前线程中获取。(这个操作Hibernate在内部已经帮我们做好了。我们可以通过sessionFactory.getCurrentSession()来获取与本地线程绑定的session对象。不过需要事先在核心配置文件中进行配置,否则会报异常。)

具体配置如下:

<property name="hibernate.current_session_context_class">thread</property>

配置好之后在关闭Session时就不需要我们手动关闭了。当线程他会自动关闭。如果加上手动关闭会报异常: Session was already closed

Hibernate中多表操作:

首先说表与表的三种关系:

  • 一对一的关系:A表的一条记录对应B表的一条记录。B表中的一条记录也只对应A表中的一条记录(建表原则:可以让一方的主键对应另一方的主键)

  •  一对多关系:A表的一条记录对应B表的多条记录。B表中的一条记录对应A表中的一条记录(建表原则:在多的一方创建外键指向一的一方的主键)

  • 多对多关系:A表中的一条记录对应B表中的多条记录。B表中的一条记录也可以对应A表中的多条记录。(建表原则:创建一个中间表,中间表至少两个字段作为外键分别指向双方主键) 

Hibernate中的一对多操作

示例:一用户角色只能在一个地区,但是一个地区可以有很多用户。

创建两个持久化类(省略一堆get和set):

public class NativePlace {
	private Integer id;
	private String nativePlace;
	//一个地区有多个用户
	private Set<User> userSet = new HashSet<User>();

}

 

public class User {
	private Integer id;
	private String userName;
	private String password;
	private String email;
	private Double money;

	//一个用户对应一个地区
	private NativePlace nativePlace;

}

配置映射文件NativePlace.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="cn.itcast.entity.NativePlace" table="t_nativer">
		<id name="id" column="id">
                        <!--主键生成策略-->
			<generator class="native"></generator>
		</id>
		<property name="nativePlace" column="native_place"></property>

		<!-- (NativePlace中用的集合是set)set标签name属性值:多的一方的集合的属性名称 -->
		<set name="userSet">
			<!-- 一对多建表,有外键
				hibernate机制:在一和多的那一方都配置外键
				column属性值:外键名称 
			-->
			<key column="jid"></key>
			<!-- 此为一的一方 映射 多的一方的全类名 -->
			<one-to-many class="cn.itcast.entity.User"></one-to-many>
		</set>
	</class>
</hibernate-mapping> 

 User.hbm.xml(除去相关的成员字段映射配置只需加上一条)

<!-- 
    name属性:在User类中地区用nativePalce属性表示
-->
<many-to-one name="nativePlace" class="cn.itcast.entity.NativePlace" column="jid"></many-to-one>

核心配置文件中引入映射关系:

<!-- 引入映射配置文件 -->
<mapping resource="cn/itcast/entity/User.hbm.xml" />
<mapping resource="cn/itcast/entity/NativePlace.hbm.xml" />

一对多级联操作:

  1. 级联保存:添加一个地区,为此地区添加多个用户。
  2. 级联删除:删除一个地区,删除该地区的所有用户。

级联保存测试:

public class HibernateDemo04 {
	
	public static void main(String[] args) {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();
			
			//创建新的地区
			NativePlace nativePlace = new NativePlace();
			nativePlace.setNativePlace("陕西省");
			
			//创建多个用户
			User user1 = new User("杨过", "121", "121@xx.com", 200.0);
			User user2 = new User("小龙女", "121", "121@xx.com", 200.0);
			//为用户设置地区
			user1.setNativePlace(nativePlace);
			user2.setNativePlace(nativePlace);
			
			//将用户添加进集合
			nativePlace.addUser(user1);
			nativePlace.addUser(user2);
			
			//保存到数据库
			session.save(nativePlace);
			session.save(user1);
			session.save(user2);
			
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			session.close(); 
		}
	}

}

结果如下:

 

 上述代码中是将双方都保存了。还可以只保存一方。那就需要先确定主控方。比如现在的主控方是用户,所以只需在
用户的映射文件中进行配置,如下:(增加了cascade属性)

<many-to-one name="nativePlace" class="cn.itcast.entity.NativePlace" column="jid" cascade="save-update"></many-to-one>

测试一下只保存一方是否可以级联到另一方(只需要将上述代码中业务内容修改一下即可):

	NativePlace nativePlace = new NativePlace();
	nativePlace.setNativePlace("广东省");
			
	User user = new User("郭靖", "121", "121@xx.com", 200.0);

	user.setNativePlace(nativePlace);
			
	nativePlace.addUser(user);
			
	//现在只需要保存主控方即可。即用户。级联是双向的。此处保存用户的同时级联地区。
	session.save(user);

结果:

 

 如果想保存的那一方是地区,则在NativePlace.hbm.xml中的set标签上添加该属性即可。

级联删除:

在NativePlace.hbm.xml映射配置文件中为cascade属性添加值delete。如下:

<set name="userSet" cascade="delete">
			
    <key column="jid"></key>
			
    <one-to-many class="cn.itcast.entity.User"></one-to-many>
</set>
public static void main(String[] args) {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();
			
			//获取地区信息
			NativePlace nativePlace = session.get(NativePlace.class, 2);
			//删除该地区信息的同时会级联到用户
			session.delete(nativePlace);
			
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			session.close(); 
		}
	}

 

一对多修改操作:

public static void main(String[] args) {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();
			
			//获取用户
			User user = session.get(User.class, 2);
			//获取地区信息
			NativePlace nativePlace = session.get(NativePlace.class, 2);
			//修改该用户的地区并保存。
			user.setNativePlace(nativePlace);
			session.save(user);
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			session.close(); 
		}
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值