對象-關系映射(Object/Relation Mapping,簡稱ORM),是隨着面向對象的軟件開發方法發展而產生的,是一種為了解決面向對象與關系數據庫存在的互不匹配的現象的技術,本質上就是將數據從一種形式轉換到另外一種形式。
面向對象的開發方法是當今企業級應用開發環境中的主流開發方法,關系數據庫是企業級應用環境中永久存放數據的主流數據存儲系統。對象和關系數據是業務實體的兩種表現形式,業務實體在內存中表現為對象,在數據庫中表現為關系數據。內存中的對象之間存在關聯和繼承關系,而在數據庫中,關系數據無法直接表達多對多關聯和繼承關系。因此,對象-關系映射(ORM)系統一般以中間件的形式存在,主要實現程序對象到關系數據庫數據的映射。
簡單的說,ORM是通過使用描述對象和數據庫之間映射的元數據,將java程序中的對象自動持久化到關系數據庫中
Hibernate在實現ORM功能的時候主要用到的文件有:映射類(*.java)、映射文件(*.hbm.xml)和數據庫配置文件(*.properties/*.cfg.xml),它們各自的作用如下。
映射類(*.java):它是描述數據庫表的結構,表中的字段在類中被描述成屬性,將來就可以實現把表中的記錄映射成為該類的對象了。
映射文件(*.hbm.xml):它是指定數據庫表和映射類之間的關系,包括映射類和數據庫表的對應關系、表字段和類屬性類型的對應關系以及表字段和類屬性名稱的對應關系等。
數據庫配置文件(*.properties/*.cfg.xml):它是指定與數據庫連接時需要的連接信息,比如連接哪種數據庫、登錄數據庫的用戶名、登錄密碼以及連接字符串等。當然還可以把映射類的地址映射信息放在這里。
兩個對象之間一對的關系,例如:Person(人)-IdCard(身份證)實例
有兩種策略可以實現一對一的關聯映射:
*主鍵關聯:即讓兩個對象具有相同的主鍵值,以表明它們之間的一一對應的關系;數據庫表不會有額外的字段來維護它們之間的關系,僅通過表的主鍵來關聯。
單向一對一唯一外鍵關聯例子連接

package cn.itcast.i_hbm_oneToOne; public class Person { private Integer id; private String name; private IdCard idCard; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public IdCard getIdCard() { return idCard; } public void setIdCard(IdCard idCard) { this.idCard = idCard; } @Override public String toString() { return "[Person��id=" + id + ", name=" + name + "]"; } }

package cn.itcast.i_hbm_oneToOne; public class IdCard { private Integer id; private String number; private Person person; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } @Override public String toString() { return "[IdCard��id=" + id + ", number=" + number + "]"; } }

<?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 package="cn.itcast.i_hbm_oneToOne"> <class name="Person" table="person"> <id name="id"> <generator class="native"></generator> </id> <property name="name"/> <!-- idCard屬性,IdCard類型。 表達的是本類與IdCard的一對一。 采用基於外鍵的一對一映射方式,本方無外鍵方。 property-ref屬性: 寫的是對方映射中外鍵列對應的屬性名。 --> <one-to-one name="idCard" class="IdCard" property-ref="person"/> </class> </hibernate-mapping>

<?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 package="cn.itcast.i_hbm_oneToOne"> <class name="IdCard" table="idCard"> <id name="id"> <generator class="native"></generator> </id> <property name="number"/> <!-- person屬性,Person類型。 表達的是本類與Person的一對一。 采用基於外鍵的一對一映射方式,本方有外鍵方。 --> <many-to-one name="person" class="Person" column="personId" unique="true"></many-to-one> </class> </hibernate-mapping>

package cn.itcast.i_hbm_oneToOne; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.junit.Test; import com.java1234.util.HibernateSessionFactory; public class App { private static SessionFactory sessionFactory =HibernateSessionFactory.getSessionFactory(); // 保存,有關聯關系 @Test public void testSave() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- // 新建對象 Person person = new Person(); person.setName("張三"); IdCard idCard = new IdCard(); idCard.setNumber("100000011X"); // 關聯起來 // person.setIdCard(idCard); idCard.setPerson(person); // 保存 session.save(person); session.save(idCard); // -------------------------------------------- session.getTransaction().commit(); session.close(); } // 獲取,可以獲取到關聯的對方 @Test public void testGet() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- // 獲取一方,並顯示另一方信息 // Person person = (Person) session.get(Person.class, 1); // System.out.println(person); // System.out.println(person.getIdCard()); IdCard idCard = (IdCard) session.get(IdCard.class, 1); System.out.println(idCard); System.out.println(idCard.getPerson()); // -------------------------------------------- session.getTransaction().commit(); session.close(); } // 解除關聯關系:一對一中,只能有外鍵方可以維護關聯關系。 @Test public void testRemoveRelation() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- // 從有外鍵方解除關系,可以。 // IdCard idCard = (IdCard) session.get(IdCard.class, 1); // idCard.setPerson(null); // 從無外鍵方解除關系,不可以。 Person person = (Person) session.get(Person.class, 1); person.setIdCard(null); // -------------------------------------------- session.getTransaction().commit(); session.close(); } // 刪除對象,對關聯對象的影響 @Test public void testDelete() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- // a, 如果沒有關聯的對方:能刪除。 // b, 如果有關聯的對方且可以維護關聯關系(有外鍵方),他就會先刪除關聯關系,再刪除自己。 // c, 如果有關聯的對方且不能維護關聯關系(無外鍵方),所以會直接執行刪除自己,就會有異常。 IdCard idCard = (IdCard) session.get(IdCard.class, 1); session.delete(idCard); // Person person = (Person) session.get(Person.class, 1); // session.delete(person); // -------------------------------------------- session.getTransaction().commit(); session.close(); } }
配置文件hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!--數據庫連接設置 --> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="connection.url"> jdbc:mysql://localhost:3306/mytest </property> <property name="connection.username">root</property> <property name="connection.password">root</property> <!-- 方言 --> <property name="dialect"> org.hibernate.dialect.MySQL5Dialect </property> <!-- 控制台顯示SQL --> <property name="show_sql">true</property> <!-- 自動更新表結構 --> <property name="hbm2ddl.auto">update</property> <mapping resource="cn/itcast/i_hbm_oneToOne/IdCard.hbm.xml" /> <mapping resource="cn/itcast/i_hbm_oneToOne/Person.hbm.xml" /> </session-factory> </hibernate-configuration>
單向一對一主鍵關聯例子連接
其余代碼不變只需修改如下文件

<?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 package="cn.itcast.i_hbm_oneToOne2"> <class name="Person" table="person2"> <id name="id"> <generator class="native"></generator> </id> <property name="name"/> <!-- idCard屬性,IdCard類型。 表達的是本類與IdCard的一對一。 采用基於主鍵的一對一映射方式,本方無外鍵方。 --> <one-to-one name="idCard" class="IdCard"></one-to-one> </class> </hibernate-mapping>

<?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 package="cn.itcast.i_hbm_oneToOne2"> <class name="IdCard" table="idCard2"> <id name="id"> <!-- 當使用基於主鍵的一對一映射時, 有外鍵方的主鍵生成策略一定要是foreign。 參數property: 生成主鍵值時所根據的對象。 --> <generator class="foreign"> <param name="property">person</param> </generator> </id> <property name="number"/> <!-- person屬性,Person類型。 表達的是本類與Person的一對一。 采用基於主鍵的一對一映射方式,本方有外鍵方。 --> <one-to-one name="person" class="Person" constrained="true"></one-to-one> </class> </hibernate-mapping>