• Hibernate一对一


    1.使用共享主键方式

    <class name="com.tazi.domin.User" table="USERS">
    	<id name="id"  type="java.lang.Integer">
    		<column name="ID"/>
    		<generator class="identity"/>
    	</id>
    	<property name="username" type="string" column="USERNAME"/>	
    	<property name="password" type="string" column="PASSWORD"/>		
    	<one-to-one name="profile" class="com.tazi.domin.Profile"cascade="none />
    </class> 
       <class name="com.tazi.domin.Profile" table="profile" catalog="hib" >
            <id name="id" type="java.lang.Integer">
                <column name="ID" />
                <generator class="foreign" >
                	<param name="property">user</param>
                </generator>
            </id>
             
            <property name="birth" type="java.sql.Timestamp" column="BIRTHDATE"/>
            <property name="age" type="java.lang.Integer" column="AGE"/>
            <one-to-one name="user" class="com.tazi.domin.User" />
        </class>
    

    测试:

    (1). 

    profile.setUser(user);//profile的主键依赖于user的主键
    user.setProfile(profile);

    session.save(user);//user中one-to-one 设置cascade=none

    则实际只保存了user,这是显然的。

    (2).session.save(user); //user中one-to-one设置cascade=all

    则保存user后保存profile

    Hibernate: 
        insert 
        into
            USERS
            (USERNAME, PASSWORD) 
        values
            (?, ?)
    Hibernate: 
        insert 
        into
            hib.profile
            (BIRTHDATE, AGE, ID) 
        values
            (?, ?, ?)
    

    (3). session.save(profile); //profile 的one-to-one中没有进行任何cascade设置,甚至cascade="none"执行结果与(2)相同。因为profile的主键是由表user产生的。

    (4).User user=(User)session.get(User.class, 2);发现Hibernate使用两次左外连接,显然有些多余。当session.get(Profile.class,2)时结果也是两次外连接。

    Hibernate: 
        select
            user0_.ID as ID1_2_,
            user0_.USERNAME as USERNAME1_2_,
            user0_.PASSWORD as PASSWORD1_2_,
            profile1_.ID as ID2_0_,
            profile1_.BIRTHDATE as BIRTHDATE2_0_,
            profile1_.AGE as AGE2_0_,
            user2_.ID as ID1_1_,
            user2_.USERNAME as USERNAME1_1_,
            user2_.PASSWORD as PASSWORD1_1_ 
        from
            USERS user0_ 
        left outer join
            hib.profile profile1_ 
                on user0_.ID=profile1_.ID 
        left outer join
            USERS user2_ 
                on profile1_.ID=user2_.ID 
        where
            user0_.ID=?
    

    (5).如果此时在Profile的one-to-one中设置fetch="select",则结果如下:

    Hibernate: 
        select
            user0_.ID as ID1_1_,
            user0_.USERNAME as USERNAME1_1_,
            user0_.PASSWORD as PASSWORD1_1_,
            profile1_.ID as ID2_0_,
            profile1_.BIRTHDATE as BIRTHDATE2_0_,
            profile1_.AGE as AGE2_0_ 
        from
            USERS user0_ 
        left outer join
            hib.profile profile1_ 
                on user0_.ID=profile1_.ID 
        where
            user0_.ID=?
    

    可见,在一对一关联中,Hibernate默认使用左外连接的方式进行查询。

    (6).在Profile中 增加constrained="true"

     <one-to-one name="user" class="com.tazi.domin.User" constrained="true"/>

    则User user=(User)session.get(User.class, 2);执行结果如下:

    Hibernate: 
        select
            user0_.ID as ID1_1_,
            user0_.USERNAME as USERNAME1_1_,
            user0_.PASSWORD as PASSWORD1_1_,
            profile1_.ID as ID2_0_,
            profile1_.BIRTHDATE as BIRTHDATE2_0_,
            profile1_.AGE as AGE2_0_ 
        from
            USERS user0_ 
        left outer join
            hib.profile profile1_ 
                on user0_.ID=profile1_.ID 
        where
            user0_.ID=?
    

     其实 增加constrained="true",单独获取Profile(session.get(Profile.class,3)),会发现并没有立刻加载User

    Hibernate: 
        select
            profile0_.ID as ID2_0_,
            profile0_.BIRTHDATE as BIRTHDATE2_0_,
            profile0_.AGE as AGE2_0_ 
        from
            hib.profile profile0_ 
        where
            profile0_.ID=?
    

    (7).delete操作时,会先删除不被其他表引用的表记录

    User user=(User)session.get(User.class, 4);
    session.delete(user); 
    Hibernate: 
        delete 
        from
            hib.profile 
        where
            ID=?
    Hibernate: 
        delete 
        from
            USERS 
        where
            ID=?
    

     2.唯一外键方式

    <class name="com.tazi.domin.User" table="USERS">
    		<id name="id"  type="java.lang.Integer">
    			<column name="ID"/>
    			<generator class="identity"/>
    		</id>
    		<property name="username" type="string" column="USERNAME"/>	
    		<property name="password" type="string" column="PASSWORD"/>	
    		
    		<one-to-one name="profile" class="com.tazi.domin.Profile"
    		cascade="all" property-ref="user"
    		 />
    </class>
    
        <class name="com.tazi.domin.Profile" table="profile" catalog="hib" >
            <id name="id" type="java.lang.Integer">
                <column name="ID" />
                <generator class="identity" />            	   
            </id>
            <property name="birth" type="java.sql.Timestamp" column="BIRTHDATE"/>
            <property name="age" type="java.lang.Integer" column="AGE"/>
            <many-to-one name="user" class="com.tazi.domin.User" unique="true" >
            	<column name="USERID"/>
            </many-to-one>
        </class>
    

     (1).session.save(user)的执行结果如下:

    Hibernate: 
        insert 
        into
            USERS
            (USERNAME, PASSWORD) 
        values
            (?, ?)
    Hibernate: 
        insert 
        into
            hib.profile
            (BIRTHDATE, AGE, USERID) 
        values
            (?, ?, ?)
    

    (2).session.get(User.class,14)的结果:

    Hibernate: 
        select
            user0_.ID as ID1_1_,
            user0_.USERNAME as USERNAME1_1_,
            user0_.PASSWORD as PASSWORD1_1_,
            profile1_.ID as ID2_0_,
            profile1_.BIRTHDATE as BIRTHDATE2_0_,
            profile1_.AGE as AGE2_0_,
            profile1_.USERID as USERID2_0_ 
        from
            USERS user0_ 
        left outer join
            hib.profile profile1_ 
                on user0_.ID=profile1_.USERID 
        where
            user0_.ID=?
    

    它根据外键取出关联表(profile)的数据

    (3)如果在主方(User)的one-to-one配置中去掉property-ref="user",

    session.get(User.class,14)的结果如下:

        select
            user0_.ID as ID1_1_,
            user0_.USERNAME as USERNAME1_1_,
            user0_.PASSWORD as PASSWORD1_1_,
            profile1_.ID as ID2_0_,
            profile1_.BIRTHDATE as BIRTHDATE2_0_,
            profile1_.AGE as AGE2_0_,
            profile1_.USERID as USERID2_0_ 
        from
            USERS user0_ 
        left outer join
            hib.profile profile1_ 
                on user0_.ID=profile1_.ID 
        where
            user0_.ID=?
    

      它根据主键相等作为连接条件,显然是错误的。所以必须加上property-ref="user",它指示User在加载关联的Profile时连接条件是通过哪一个属性(默认是id所对应的属性)

     (4).session.delete(user)的执行结果与上面1中的delete执行结果相同,都是根据id删除的,而不是根据外键,虽然外键也是唯一的。因为在delete之前,必须先得到数据库中记录对应的持久化对象,取得后id属性一定是已知的。如果在主方(独立方)没有设置cascade="all",则session.delete(user)不会成功,这是由于数据库中外键约束引起的。

  • 相关阅读:
    最小乘积(基本型)
    删除数组零元素
    大小写转换
    矩阵乘法
    字串统计
    出现次数最多的整数
    Anagrams问题
    前缀表达式
    2的次幂表示
    POJ
  • 原文地址:https://www.cnblogs.com/tazi/p/2285190.html
Copyright © 2020-2023  润新知