Hibernate多对一关联映射(单向)

双向多对一关联映射在开发中用的非常多,为了更好的理解双向多对一,我们先来讨论单向多对一的关联映射,下面我们通过一个例子来体会,用户和组的关系为多对一,多个用户属于一个组,类图如下:


注:上图表示单向的关联,即通过User可以关联到Group,而通过Group不能关联到User。


映射的数据库表为:


注:从映射的数据库表可以看出,多个用户对应一个组,即多对一关系。


User.java:

public class User {
	
	/*用户ID*/
	private int id;
	/*用户名*/
	private String name;
	/*用户和组的关系(单向多对一)*/
	private Group group;

	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;
	}

	public Group getGroup() {
		return group;
	}

	public void setGroup(Group group) {
		this.group = group;
	}
}

Group.java:

public class Group {
	/*组ID*/
	private int id;
	/*组名*/
	private String name;

	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;
	}
}

User.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lixue.bean">
	<class name="User" table="t_user">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		
		<!-- 设置用户和组的关系(单向多对一,在多的一端加一个外键,通过外键来维护关系)cascade="save-update"表示级联保存和级联更新 -->
		<many-to-one name="group" column="group_id" cascade="save-update"/>
	</class>
</hibernate-mapping>
注:多对一关联映射是在多的一端加一个外键来维护关系。cascade表示级联,如上述代码中配置的cascade="save-update"表示级联保存和级联更新,如果没有设置级联,那么必须显示的保存对象,否则会报错。


Group.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lixue.bean">
	<class name="Group" table="t_group">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
	</class>
</hibernate-mapping>
注:因为是单向的,所以Group这个配置文件就是普通的属性映射。


测试类:

public void testSave1(){
		
		/*定义Session*/
		Session session = null;
		/*定义Transaction*/
		Transaction transaction = null;
		
		try {
			session = HibernateUtils.getSession();
			transaction = session.beginTransaction();
			
			/*创建组并设置属性*/
			Group group = new Group();
			group.setName("测试组");
			
			/*创建用户并设置属性*/
			User user1 = new User();
			user1.setName("小廖");
			user1.setGroup(group);
			
			/*创建用户并设置属性*/
			User user2 = new User();
			user2.setName("小明");
			user2.setGroup(group);
			
			/*保存用户*/
			session.save(user1);
			session.save(user2);
			
			/**
			 * 提交事物,在清理缓存的时候发生错误:TransientObjectException
			 * 因为Group为Transient瞬时状态,没有被Session管理,在数据库中没有与之匹配的数据
			 * 而User为Persistent状态,在清理缓存时Hibernate在缓存中无法找到Group对应的对象
			 * 结论:Persistent状态的对象不能引用Transient状态的对象
			 */
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		} finally{
			HibernateUtils.closeSession(session);
		}
	}

注:上述代码是在User.hbm.xml文件没有配置cascade="save-update"的前提下测试的,上述程序没有显示的保存group,并且配置文件没有设置级联保存,所以会发生错误:TransientObjectException即处于Persistent状态的User对象不能引用处于Transient状态的Group对象。


测试二:

	public void testSave2(){
		
		/*定义Session*/
		Session session = null;
		/*定义Transaction*/
		Transaction transaction = null;
		
		try {
			session = HibernateUtils.getSession();
			transaction = session.beginTransaction();
			
			/*创建组并设置属性*/
			Group group = new Group();
			group.setName("测试组");
			
			/*创建用户并设置属性*/
			User user1 = new User();
			user1.setName("小廖");
			user1.setGroup(group);
			
			/*创建用户并设置属性*/
			User user2 = new User();
			user2.setName("小明");
			user2.setGroup(group);
			
			/*保存组,保存用户*/
			session.save(group);
			session.save(user1);
			session.save(user2);
			
			/**
			 * 提交事物
			 * 这种方式可以正确的保存数据,因为Group和User都是Persistent状态的数据
			 * 在Hibernate清理缓存时在Session中可以找到关联对象
			 */
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		} finally{
			HibernateUtils.closeSession(session);
		}
	}
	
注:上述代码可以成功保存对象,虽然配置文件中没有设置级联保存,但是程序中显示的调用了保存group的代码:session.save(group);所以group对象就成了Persistent状态了,必然可以保存成功。


测试三:

/**
	 * 通过上面这种方式即同时保存组合User的方式提交事务是没有问题的,
	 * 其实还有一种更简单的方式,那就是在XML文件中配置级联操作
	 * cascade="save-update"
	 */
	public void testSave3(){
		
		/*定义Session*/
		Session session = null;
		/*定义Transaction*/
		Transaction transaction = null;
		
		try {
			session = HibernateUtils.getSession();
			transaction = session.beginTransaction();
			
			/*创建组并设置属性*/
			Group group = new Group();
			group.setName("测试组");
			
			/*创建用户并设置属性*/
			User user1 = new User();
			user1.setName("小廖");
			user1.setGroup(group);
			
			/*创建用户并设置属性*/
			User user2 = new User();
			user2.setName("小明");
			user2.setGroup(group);
			
			/*因为设置了级联保存,所以不需要保存组,保存用户*/
			//session.save(group);
			session.save(user1);
			session.save(user2);
			
			/**
			 * 提交事物
			 * 这种方式可以正确的保存数据,因为设置了级联保存和级联更新
			 * 在Hibernate清理缓存时在Session中可以找到关联对象
			 */
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		} finally{
			HibernateUtils.closeSession(session);
		}
	}
	
注:上述程序是在User.hbm.xml文件中配置了cascade="save-update"的前提下测试的,因为配置了级联保存和级联更新,所以即使在上述测试中没有显示的保存group对象,依然可以成功的保存。


测试四:

/**
	 * 单向多对一关联
	 * 我们可以通过多的一端加载一的一端
	 * 即通过User这一端加载Group这一端
	 */
	public void testFind(){
		/*加载User*/
		User user = (User) HibernateUtils.getSession().get(User.class, 1);
		
		/*打印用户名*/
		System.out.println("user.name=" + user.getName());
		/*打印用户所在组*/
		System.out.println("user.group.name=" + user.getGroup().getName());
	}
注:我们的应用时单向多对一关联映射,即通过多的一端即User,可以加载一的一端即Group的一端。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hibernate是一个Java持久化框架,它能够将Java对象映射到数据库中的表格,同时支持各种关系数据库,如MySQL、Oracle等。在Hibernate中,对于一对一、一对多和多对多的关系,我们可以通过以下方式进行映射。 一对一关系:在Hibernate中,可以通过主键关联和外键关联来实现一对一关系的映射。主键关联是指两个实体之间的关联通过主键来进行,可以使用@PrimaryKeyJoinColumn注解将两个实体关联起来。外键关联是指通过一个实体引用另一个实体的主键作为外键,使用@JoinColumn注解来指定外键属性。 一对多关系:在Hibernate中,一对多关系通常通过外键关联来实现。在一的一方,使用@OneToMany注解来定义一对多关系,同时使用@JoinColumn注解指定外键属性。在多的一方,使用@ManyToOne注解来定义多对一关系,并使用@JoinColumn注解指定外键属性。 多对多关系:在Hibernate中,多对多关系通常通过中间表来实现。在多对多的两个实体中,使用@ManyToMany注解来定义多对多关系。同时,需要在中间表中创建两个外键,分别与两个实体的主键关联,并使用@JoinTable注解来指定中间表的表名和两个外键的列名。 总结:通过Hibernate的注解方式,可以方便地实现一对一、一对多和多对多关系的映射。通过合理地使用注解,可以减少编写映射文件的工作量,提高开发效率。同时,Hibernate还提供了在运行时自动生成表结构的功能,可以根据Java实体类来动态创建或更新对应的数据库表格,从而提高系统的可维护性和灵活性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值