1. 程式人生 > >hibernate雙向一對一主鍵關聯對映XML與註解版

hibernate雙向一對一主鍵關聯對映XML與註解版

雙向一對一關聯對映原理: 

雙向的主鍵關聯其實是單向一對一主鍵關聯的一種特殊情況,只不過要在關聯物件的兩端的對映檔案中都要進行<one-to-one>的配置,另外還要在主對映的主鍵一端採用foreign外來鍵關聯屬性。

        這裡同樣使用Person和IdCard來討論,一個人對應著一個唯一的身份證,而且一個身份證也唯一對映著一個人,所以這就產生了雙向的關聯關係,Person的主鍵同樣也是IdCard的主鍵,分別是主鍵的同時也是外來鍵,這種關聯關係成為雙向一對一對映,表現到關係模型中可如下圖:


(1)XML版

SQL檔案:

CREATE TABLE `person` (
  `id` varchar(255) NOT NULL,
  `pname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `idcard` (
  `id` varchar(255) NOT NULL,
  `cardnum` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Person類:

package Hibernate_demo1.Demo11.Entity;

public class Person {
	private String id;
	private String pname;
	private IdCard idcards;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public IdCard getIdcards() {
		return idcards;
	}
	public void setIdcards(IdCard idcards) {
		this.idcards = idcards;
	}
	
}

IdCard類:

package Hibernate_demo1.Demo11.Entity;

public class IdCard {
	
	private String id;
	private String cardNum;
	private Person persons;
	
	
	
	public Person getPersons() {
		return persons;
	}
	public void setPersons(Person persons) {
		this.persons = persons;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getCardNum() {
		return cardNum;
	}
	public void setCardNum(String cardNum) {
		this.cardNum = cardNum;
	}
}

IdCard.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="Hibernate_demo1.Demo11.Entity.IdCard" table="IdCard">  
        <id name="id" type="java.lang.String"> 
            <column name="id"/>
            <generator class="uuid">  
            </generator>  
        </id>  
        <property name="cardNum" column="cardNum"/>
        <!-- 
                        在對映檔案中新增外來鍵屬性persons,並新增對應的<one-to-one>標籤
                        目的是強制約束person類來實現一對一的對映關係,最後在對映中將constrained屬性設為true
                        保證強制約束關係。
         -->
        <one-to-one name="persons" constrained="true"></one-to-one>
    </class>  
</hibernate-mapping>  

雙向一對一唯一外來鍵對映關鍵對映程式碼——在IdCard端新加入如下標籤對映:

<one-to-one name="person"property-ref="idCard"/>

 注意:一對一唯一外來鍵關聯雙向採用<one-to-one>標籤對映,必須指定<one-to-one>標籤中的property-ref屬性為關係欄位的名稱。

Person.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="Hibernate_demo1.Demo11.Entity.Person" table="person">  
        <id name="id">  
            <generator class="uuid">  
            </generator>  
        </id>  
        
        <property name="pname" column="pname"/>  
        
        <!--  
            one-to-one標籤指示Hibernate如何載入其關聯物件,預設根據主鍵載入,也就是拿到關係欄位值,根據對端的主鍵來載入關聯物件 
         --> 
        <one-to-one name="idcards"></one-to-one> 
    </class>  
</hibernate-mapping>  

測試類:
package Hibernate_demo1.Demo11;

import org.hibernate.Session;

import Hibernate_demo1.Demo11.Entity.IdCard;
import Hibernate_demo1.Demo11.Entity.Person;
import Hibernate_demo1.Demo11.Util.HibernateUtils;

public class App 
{
    public static void main( String[] args )
    {
    	Session session = null;
    	try{  
    		  
    	    session = HibernateUtils.getSession();
    	    session.beginTransaction();  
    	      
    	    //建立person物件,並儲存  
            Person person=new Person();  
            person.setPname("fendo");  
            session.save(person);  
              
            //建立idCard物件,並儲存  
            IdCard idcard=new IdCard();  
            idcard.setCardNum("123456789");  
            idcard.setPersons(person);
            session.save(idcard);  
    	      
    	    session.getTransaction().commit();  
    	}catch(Exception e){  
    	    e.printStackTrace();  
    	    session.getTransaction().rollback();  
    	}finally{  
    	    HibernateUtils.closeSession(session);  
    	}
    }
}

執行結果如下:
Hibernate: 
    insert 
    into
        person
        (pname, id) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        IdCard
        (cardNum, id) 
    values
        (?, ?)

執行結果如下:

Person表


idcard表


(2)註解版

Person類:

package Hibernate_demo1.Demo12.Entity;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name="person")
public class Person {
	
	@Id
        @GenericGenerator(name="uuidGenerator", strategy="uuid")
        @GeneratedValue(generator="uuidGenerator")
	private String id;
	
	@Column(name="pname")
	private String pname;
	
        @OneToOne(cascade=CascadeType.ALL)
        @PrimaryKeyJoinColumn
	private IdCard idcards;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public IdCard getIdcards() {
		return idcards;
	}
	public void setIdcards(IdCard idcards) {
		this.idcards = idcards;
	}
	
}

IdCard類:

package Hibernate_demo1.Demo12.Entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name="idcard")
public class IdCard {
	
	@Id
        @GenericGenerator(name="uuidGenerator", strategy="uuid")
        @GeneratedValue(generator="uuidGenerator")
	private String id;
	
	@Column(name="cardNum")
	private String cardNum;
	
	@OneToOne
        @PrimaryKeyJoinColumn
	private Person persons;
	
	
	
	public Person getPersons() {
		return persons;
	}
	public void setPersons(Person persons) {
		this.persons = persons;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getCardNum() {
		return cardNum;
	}
	public void setCardNum(String cardNum) {
		this.cardNum = cardNum;
	}
}

測試類:

package Hibernate_demo1.Demo12;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import Hibernate_demo1.Demo12.Entity.IdCard;
import Hibernate_demo1.Demo12.Entity.Person;



public class App 
{
    public static void main( String[] args )
    {
    	SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();  
    	Session session = sessionFactory.getCurrentSession();  
    	Transaction tx = session.beginTransaction();  
        
    	//建立person物件,並儲存  
        Person person=new Person();  
        person.setPname("fendo");  
        session.save(person);  
          
        //建立idCard物件,並儲存  
        IdCard idcard=new IdCard();  
        idcard.setCardNum("123456789");  
        idcard.setPersons(person);
        session.save(idcard);  
    	
        tx.commit();
        session.close();
    }
}

執行結果如下:
Hibernate: 
    insert 
    into
        person
        (pname, id) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        idcard
        (cardNum, id) 
    values
        (?, ?)