hibernate 一对一

2017-10-30  本文已影响24人  siriusing
public class Person {

    private Integer pid;
    private String name;
    private Address address;
    ...
}
----------------------------------------
public class Address {
    private Integer aid;
    private String name;
    private Person person;
    ...

}

 

1.0 基于外键的一对一


<?xml version="1.0" encoding="UTF-8"?>
<!-- Person.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
    <class name="Person" table="t_Person"  >
    
        <id name="pid" column="pid">
            <generator class="native"></generator>
        </id>
        <property name="name"></property>

        <many-to-one name="address" class="Address" column="aid" unique="true"></many-to-one>
    </class>

</hibernate-mapping>




<?xml version="1.0" encoding="UTF-8"?>
<!-- Address.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
    <class name="Address" table="t_Address"  >
    
        <id name="aid" column="aid">
            <generator class="native"></generator>
        </id>
        <property name="name"></property>

        <!-- property-ref指定关联类的一个属性,来对应自己,意思是:person的address指向我 -->
        <one-to-one name="person" property-ref="address" class="Person"/>
    </class>

</hibernate-mapping>


mysql> show create table t_person;
+----------+--------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-----------------------------------+
| Table    | Create Table
                                   |
+----------+--------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-----------------------------------+
| t_person | CREATE TABLE `t_person` (
  `pid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `aid` int(11) DEFAULT NULL,
  PRIMARY KEY (`pid`),
  UNIQUE KEY `aid` (`aid`),
  KEY `FK41C0D9A019FE94E7` (`aid`),
  CONSTRAINT `FK41C0D9A019FE94E7` FOREIGN KEY (`aid`) REFERENCES `t_address` (`a
id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+----------+--------------------------------------------------------------------

说白了,其实是一种特殊的一对多,多个person对一个address,但是person必须不重复

1.1添加


@Test
    public void add(){
        
        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Person p=new Person("好人刘强东");
        
        Address a=new Address("中关村"); 
        
        p.setAddress(a);
        

        session.save(p);
        session.save(a);
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
            
    }

1.2查找

    @Test
    public void find(){
        
        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Person p=(Person) session.get(Person.class, 1);
        
//      System.out.println(p.getAddress());
        
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
        
    
    }

这里主要的问题是,他不级联查

Hibernate: 
    select
        person0_.pid as pid1_0_,
        person0_.name as name1_0_,
        person0_.aid as aid1_0_ 
    from
        t_Person person0_ 
    where
        person0_.pid=?

通过另一端address来查,

    @Test
    public void findByAddress(){
        
        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Address a=(Address) session.get(Address.class, 1);
        
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
        
    }

Hibernate: 
    select
        address0_.aid as aid0_1_,
        address0_.name as name0_1_,
        person1_.pid as pid1_0_,
        person1_.name as name1_0_,
        person1_.aid as aid1_0_ 
    from
        t_Address address0_ 
    left outer join
        t_Person person1_ 
            on address0_.aid=person1_.aid 
    where
        address0_.aid=?

结论: one-to-one 标签修饰后,他是主动选择每次查询都用join的,这里因为一对一不需要考虑数据集太大的问题;


@Test
    public void update(){

        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Address a=(Address) session.get(Address.class, 1);
        a.getPerson().setName("刘强东");
        
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
    
    }

Hibernate: 
    select
        address0_.aid as aid0_1_,
        address0_.name as name0_1_,
        person1_.pid as pid1_0_,
        person1_.name as name1_0_,
        person1_.aid as aid1_0_ 
    from
        t_Address address0_ 
    left outer join
        t_Person person1_ 
            on address0_.aid=person1_.aid 
    where
        address0_.aid=?
Hibernate: 
    update
        t_Person 
    set
        name=?,
        aid=? 
    where
        pid=?

1.3删除

    @Test
    public void deleteByAddress(){

        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Address a=(Address) session.get(Address.class, 1);
        
        session.delete(a);
        
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
    
    }

这里会出错,正确的方法:

@Test
    public void deleteByPerson(){

        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Person p=(Person)session.get(Person.class, 1);
        
        session.delete(p);
        
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
    
    }
    

主要是因为:

2.0 同步主键式的一对一


<?xml version="1.0" encoding="UTF-8"?>
<!-- Address.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
    <class name="Address" table="t_Address"  >
    
        <id name="aid" column="aid">
            <generator class="foreign">
                <!-- 主键根据哪个一属性对应的表来生成,这里是属性名,切记 -->
                <param name="property">person</param>
            </generator>
        </id>
        <property name="name"></property>
        <!--
            constrained: 约束
            name:依然是属性名
         -->
        <one-to-one name="person" constrained="true"/>
    </class>

</hibernate-mapping>


<?xml version="1.0" encoding="UTF-8"?>
<!-- Person.hbm.xml -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.sirius.bean">
    <class name="Person" table="t_Person"  >
    
        <id name="pid" column="pid">
            <!-- 由这里提供主键 -->
            <generator class="native"></generator>
        </id>
        <property name="name"></property>

        <one-to-one name="address"/>
    </class>

</hibernate-mapping>

2.1 添加


@Test
    public void add(){
        
        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Person p=new Person("好人刘强东");
        
        Address a=new Address("中关村"); 
        
        a.setPerson(p);
        p.setAddress(a);
        
        session.save(p);
        session.save(a);
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
            
    }

结果:

Hibernate: 
    insert 
    into
        t_Person
        (name) 
    values
        (?)
Hibernate: 
    insert 
    into
        t_Address
        (name, aid) 
    values
        (?, ?)

2.2.1级联添加

        <one-to-one name="address" cascade="all"/>
    @Test
    public void add(){
        
        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Person p=new Person("好人刘强东");
        
        Address a=new Address("中关村"); 
        
        a.setPerson(p);
        p.setAddress(a);
        
        session.save(p);
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
            
    }

Hibernate: 
    insert 
    into
        t_Person
        (name) 
    values
        (?)
Hibernate: 
    insert 
    into
        t_Address
        (name, aid) 
    values
        (?, ?)

2.2 更新

删掉级联,继续
考虑更新

    @Test
    public void updateByAddress(){

        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Address a=(Address) session.get(Address.class, 1);
        a.getPerson().setName("刘强东");
        
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
    
    }
    
Hibernate: 
    select
        address0_.aid as aid0_0_,
        address0_.name as name0_0_ 
    from
        t_Address address0_ 
    where
        address0_.aid=?
Hibernate: 
    select
        person0_.pid as pid1_1_,
        person0_.name as name1_1_,
        address1_.aid as aid0_0_,
        address1_.name as name0_0_ 
    from
        t_Person person0_ 
    left outer join
        t_Address address1_ 
            on person0_.pid=address1_.aid 
    where
        person0_.pid=?
Hibernate: 
    update
        t_Person 
    set
        name=? 
    where
        pid=?

2.3 删除

    @Test
    public void deleteByAddress(){

        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Address a=(Address) session.get(Address.class, 1);
        
        session.delete(a);
        
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
    
    }

结果只删除了address,因为没有设级联

2.3.1 级联删除

添加级联

<!--person-->
        <one-to-one name="address" cascade="all"/>
public void deleteByPerson(){

        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        // ------------------------------------------------------
        Person p=(Person)session.get(Person.class, 1);
        
        session.delete(p);
        
        // ------------------------------------------------------
        session.getTransaction().commit();
        session.close();
    
    }
Hibernate: 
    select
        person0_.pid as pid1_1_,
        person0_.name as name1_1_,
        address1_.aid as aid0_0_,
        address1_.name as name0_0_ 
    from
        t_Person person0_ 
    left outer join
        t_Address address1_ 
            on person0_.pid=address1_.aid 
    where
        person0_.pid=?
Hibernate: 
    delete 
    from
        t_Address 
    where
        aid=?
Hibernate: 
    delete 
    from
        t_Person 
    where
        pid=?
上一篇 下一篇

猜你喜欢

热点阅读