Hibernate笔记整理 一对一

 

///
Hibernate:
	///
	一对一关联有两种关联方式,即:主键关联和外键关联。
	Member类:
	public class Member {
		private String id;
    	private String name;
		private Integer age;
    	private IdCard card;//
		.......
	}
	IdCard类:
	public class IdCard {
		private String id;
		private String num;
		private Member member;
		........
	}
	先对这两个类解释一下,Member类代表人员,IdCard类代表了身份证,这在现实中也是一对一的关系。
	///
	1、主键关联
	Member. hbm.xml的主要片段如下:
	<hibernate-mapping package="org.louis.domain"> 
		<class name="Member" table="TEST_MEMBER">
			<id name="id" column="ID">
				<generator class="uuid.hex"></generator>
			</id>
			<property name="age" column="AGE"></property>
			<property name="name" column="NAME"></property>
			<one-to-one name="card" class="IdCard" cascade="all"></one-to-one>
			.........
		</class>
	</hibernate-mapping>
	
	IdCard.hbm.xml的配置如下:
	<hibernate-mapping package="org.louis.domain">
		<class name="IdCard" table="TEST_IDCARD">
			<id name="id" column="ID">
				<generator class="foreign"><!--使用主键关联,引用Member对应表的主键作为自己的主键--> 
					<param name="property">member</param><!--此处的member必须和下面配置的one-to-one的name属性一样 --> 
				</generator>
			</id>
			<property name="num" column="NUM"></property>
			<one-to-one name="member" class="Member" constrained="true"></one-to-one>
		</class>
	</hibernate-mapping>
	
	至此,所有的配置工作已经完成。

	测试进行测试:

	a、新增数据
	public void insert()
	{
        Session session = HibernateSessionFactory.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Member m = new Member();
        m.setAge(24);
        m.setName("Louis");
    
        IdCard card = new IdCard();
        card.setNum("123456789");
        card.setMember(m);//设置Member和IdCard关系,以便IdCard可以从Member取得主键值
        
        m.setCard(card);//设置Member和IdCard关系
        
        session.save(m);
        session.getTransaction().commit();
    }
	后台Hibernate执行的SqlServer语句是:
	Hibernate: insert into TEST_MEMBER (AGE, NAME, ID) values (?, ?, ?)
	Hibernate: insert into TEST_IDCARD (NUM, ID) values (?, ?)
	保存IdCard时使用IdCard对象中member对象的Id来为自己的Id赋值的。你现在可以查看数据库,里面两个表的主键值相同。
	
	b、加载数据
	public void getMemberById(String id)
	{
		Session session = HibernateSessionFactory.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Member m = (Member)session.load(Member.class, id);
		System.out.println(m);
		session.getTransaction().commit();
	}
	后台Hibernate执行的Sql语句是:
	    select
	        member0_.ID as ID5_1_,
	        member0_.AGE as AGE5_1_,
	        member0_.NAME as NAME5_1_,
	        idcard1_.ID as ID4_0_,
	        idcard1_.NUM as NUM4_0_ 
	    from
	        TEST_MEMBER member0_ 
	    left outer join
	        TEST_IDCARD idcard1_ 
	            on member0_.ID=idcard1_.ID 
	    where
	        member0_.ID=?
	可以看出默认采用的左外连接(左边表的所有行在右边没有得到匹配,那么右边表设置为null)的查询。
	
	如果把Member.hbm.xml中做些改动如:
	<one-to-one name="card" class="IdCard" fetch="select" cascade="all"></one-to-one>
	再次执行查询Sql语句如下:
	Hibernate: 
	    select
	        member0_.ID as ID5_0_,
	        member0_.AGE as AGE5_0_,
	        member0_.NAME as NAME5_0_ 
	    from
	        TEST_MEMBER member0_ 
	    where
	        member0_.ID=?
	Hibernate: 
	    select
	        idcard0_.ID as ID4_0_,
	        idcard0_.NUM as NUM4_0_ 
	    from
	        TEST_IDCARD idcard0_ 
	    where
	        idcard0_.ID=?
	
	可以看出生成了两条SQL语句,明显要比一条的性能低一些。
	
	c、删除操作

	Hibernate: 
	    select
	        member0_.ID as ID5_0_,
	        member0_.AGE as AGE5_0_,
	        member0_.NAME as NAME5_0_ 
	    from
	        TEST_MEMBER member0_ 
	    where
	        member0_.ID=?
	Hibernate: 
	    select
	        idcard0_.ID as ID4_0_,
	        idcard0_.NUM as NUM4_0_ 
	    from
	        TEST_IDCARD idcard0_ 
	    where
	        idcard0_.ID=?
	
	Hibernate: 
	    delete 
	    from
	        TEST_IDCARD 
	    where
	        ID=?
	Hibernate: 
	    delete 
	    from
	        TEST_MEMBER 
	    where
        ID=?

	前两条Sql语句是加载Member和关联的IdCard对象。由于在测试加载数据时改变了抓取数据方式为fetch="select"所以生成了两条,
	如果改为默认(fetch="join")则只生成一条,并且采用的是左外连接方式。在删除代码中,我只是删除了Member,但是查看数据库和
	后台的SQL语句看出也把IdCard数据删除了,这是因为我在Member.hbm.xml中的<one-to-one>设置了cascade="all"。如果不
	设置(默认为“none”),则只会删除Member对象,而不会级联删除IdCard对象。
	注意:在这个例子中,一定要注意添加数据、删除数据的先后顺序。添加数据必须先添加Member(因为IdCard的主键由Member而来),
	删除数据必须先删除IdCard(因为在IdCard.hbm.xml中设置了constrained="true"而使得两个表之间有了约束)。
	
	2、外键关联
	使用外键关联,我们还是使用这两个POJO类,只是其映射文件有所调整。调整后的映射文件如下:
	Member.hbm.xml:
	<hibernate-mapping package="org.louis.domain"> 
		<class name="Member" table="TEST_MEMBER">
			<id name="id" column="ID">
				<generator class="uuid.hex"></generator>
			</id>
			<property name="age" column="AGE"></property>
			<property name="name" column="NAME"></property>
			<one-to-one name="card" class="IdCard" fetch="join" cascade="all" property-ref="member"></one-to-one> 
			......
	</hibernate-mapping>
	
	IdCard.hbm.xml:
	<hibernate-mapping package="org.louis.domain">
	    <class name="IdCard" table="TEST_IDCARD">
	        <id name="id" column="ID">
	            <generator class="uuid.hex"></generator>
	        </id>
	        <property name="num" column="NUM"></property>
	        <many-to-one name="member" class="Member" unique="true" column="MEMBER_ID"></many-to-one>
	    </class>
	</hibernate-mapping>    
	
	依然采用上面的测试代码进行测试:
	
	a、插入数据
	
	后台Hibernate执行的SQL语句
	
	Hibernate: 
	    insert 
	    into
	        TEST_MEMBER
	        (AGE, NAME, ID) 
	    values
	        (?, ?, ?)
	Hibernate: 
	    insert 
	    into
	        TEST_IDCARD
	        (NUM, MEMBER_ID, ID) 
	    values
	        (?, ?, ?)
	
	IdCard的外键来自Member的主键。
	
	b、加载数据
	
	同上
	
	c、删除数据
	
	同上

你可能感兴趣的:(Hibernate笔记整理 一对一)