【SSH系列】Hibernate映射-- 多对一单向关联映射

在hibernate中非常重要的就是映射,在前面的博文中,小编简单的介绍了基本映射,基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用。这个比较简单,但是基础知识还是需要好好掌握的哦,还有一些关联映射,比如user && group,她们之间的关系是一对多,我们知道一个用户只能属于一个组,但是一个组可以包好N多个用户,所以他们之间的关系就是多对一的关系,接着我们来看他们的对象模型以及关系模式。

所谓多对一单向关联映射,就是 多的一端维护关联关系,在“多”的一端加入一个外键,指向“一”的一端。多的一端持有一的一端的引用,即在“多”的一端加外键,指向“一”的一端。ok,接着我们来看User and Group的对象模型以及关系模式模型,首先对象模型:

【SSH系列】Hibernate映射-- 多对一单向关联映射
       接着关系模型如下所示:

【SSH系列】Hibernate映射-- 多对一单向关联映射

接着,小编用代码来实现相应的原理,还请小伙伴们多多指教哦。

第一步、建立User和Group两个实体类,并且编写代码,首先是User类,代码如下所示:

package com.bjpowernode.hibernate;

public class User {

	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的代码,如下所示:

package com.bjpowernode.hibernate;

public class Group {
	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;
	}

}

第二步、我们要从用户看到组,所以要关联,so,需要在User里面添加Group代码,编写映射文件User.hbm.xml 和Group.hbm.xml。首先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>
    <class name="com.bjpowernode.hibernate.User" table="t_user">
    	<id name="id">
    		<generator class="native"/>
    	</id>
    	<properties name="name"/>
    	<many-to-one name="group" column="groupid" cascade="save-update"/>
    </class>
</hibernate-mapping>

接着编写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>
    <class name="com.bjpowernode.hibernate.Group" table="t_group">
    	<id name="id">
    		<generator class="native"/>
    	</id>
    		<property name="name"/>
    </class>
</hibernate-mapping>

第三步、编写Hibernate.cfg.xml映射文件里面的内容,代码如下所示:

<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory >
		<!-- MySql数据库驱动 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<!-- 数据库名称 -->
		<property name="hibernate.connection.url"> jdbc:mysql:///hibernate_many2one</property>
		<!-- 数据库的用户名 -->
		<property name="hibernate.connection.username">root</property>
		<!-- 数据库的密码 -->
		<property name="hibernate.connection.password">123456</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<!-- 显示语句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 格式排版 -->
        <!-- <property name="hibernate.format_sql">true</property> -->    

		<mapping resource="com/bjpowernode/hibernate/User.hbm.xml"/>
		<mapping resource="com/bjpowernode/hibernate/Group.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

第四步、创建数据库,并且运行ExportDB文件,我们来看一下数据库里面的信息,效果如下所示:

【SSH系列】Hibernate映射-- 多对一单向关联映射
       关联映射已经搞定,接下来向里面添加数据,看看关联如何发挥作用。
       第五步、建立Many2oneTest,编写第一个方法,如下所示:

package com.bjpowernode.hibernate;

import org.hibernate.Session;

import junit.framework.TestCase;

public class Many2oneTest extends TestCase {

	public void testSave1(){

		Session session = null;
		try{
			session = HibernateUtils.getSession();
			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);

			session.getTransaction().commit();

		}catch(Exception e){
			e.printStackTrace();
			session.getTransaction().rollback();

		}finally{
			HibernateUtils.closeSession(session);

		}
	}
}

运行这个方法,我们发现,在清理缓存的时候发生错误TransientObjectException,因为Group为Transient状态,没有被session,在数据库中没有匹配的数据,而User为persistent状态,在清理缓存时Hibernate在缓存中无法找到Group,so--Persistent状态的对象不能引用Transistent状态的对象,ok,接着,我们来改进一下相关代码如下所示:

public void testSave2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();

			Group group = new Group();
			group.setName("动力节点");
			session.save(group);

			User user1 = new User();
			user1.setName("张三");
			user1.setGroup(group);

			User user2 = new User();
			user2.setName("李四");
			user2.setGroup(group);

			session.save(user1);
			session.save(user2);

			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}	

运行,发现现在可以可以正确的保存数据,因为Group和User都是Persistent状态的对象所以在hibernate清理缓存时在session中可以找到关联对象。接着再编写一个方法,介绍一个属性,这个属性叫做级联,级联就是一些连锁性的操作,级联的意思是指定两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也需要执行相同的操作。比如保存某个用户的时候,可以级联把别人保存了。首先,修改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>
    <class name="com.bjpowernode.hibernate.User" table="t_user">
    	<id name="id">
    		<generator class="native"/>
    	</id>
    	<properties name="name"/>
    	<many-to-one name="group" column="groupid" cascade="save-update"/>
    </class>
</hibernate-mapping>

方法编写,如下所示:

	public void testSave3() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			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异常
			//因为使用了级联特性
			//hibernate会首先保存User的关联对象对象Group
			//Group和User就都是Persistent状态的对象了
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}	

执行这个方法,ok,运行,如下所示:

【SSH系列】Hibernate映射-- 多对一单向关联映射
        小编寄语:该博文,小编主要简单的介绍了hibernate中的多对一单向关联映射,项目中,多对一关联映射是最常见的映射,但它是Hibernate的关联映射中最简单的一种映射关系。学习就是这样,点点滴滴的积累,下篇博文,小编将继续介绍hibernate的相关知识,敬请期待`(*∩_∩*)′!

上一篇:css知识汇总


下一篇:hibernate之关于一对一单向,双向关联映射