一、Ecplise hibernate插件安裝:java
下載zip格式的Eclipse插件,(http://sourceforge.net/projects/jboss/files/JBossTools/JBossTools4.1.x/hibernatetools-Update-4.1.1.Final_2013-12-08_01-06-33-B605.zip) mysql
Eclipse-》Help-》Install New Software.. -》add..-》Archive 選擇剛纔下載的hibernate插件sql
二、Hibernate開發步驟數據庫
1)建立hibernate配置文件(hibernate.cfg.xml):配置數據庫相關配置信息和hibernate相關初始化配置信息
編程
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 數據庫鏈接配置信息 --> <property name="connection.username">root</property> <property name="connection.password">root</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url"><![CDATA[jdbc:mysql://127.0.0.1:3306/atguigu_hibernate?useUnicode=true&characterEncoding=utf8]]></property> <!-- hibernate基本配置信息 --> <!-- hibernate數據庫方言 --> <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> <!-- 執行操做時,是否在後臺打印SQL語句 --> <property name="show_sql">true</property> <!-- 是否對SQL語句進行格式化 --> <property name="format_sql">true</property> <!-- 指定自動生成數據表的策略 --> <!-- create: 會根據*.hbm,xml文件生成新的數據表,每次都會刪除上一次的數據表從新生成表 create-drop:會根據*.hbm,xml文件生成新的數據表,可是每次sessionFactory關閉都會刪除表 update:最經常使用的值,會根據*.hbm,xml文件生成新的數據表,若是*.hbm,xml所定義的表結構與數據庫中表結果不一樣,hibernate將更新數據表結構,但不會刪除已有的行和列 validate:會和數據庫中的表進行比較,若是*.hbm,xml配置文件中的列在數據庫中不存在,則拋出異常 --> <property name="hbm2ddl.auto">update</property> <!-- 設置 Hibernate 的事務隔離級別 --> <property name="connection.isolation">2</property> <!-- 刪除對象後, 使其 OID 置爲 null --> <property name="use_identifier_rollback">true</property> <!-- 配置 C3P0 數據源 --> <property name="hibernate.c3p0.max_size">10</property> <property name="hibernate.c3p0.min_size">5</property> <property name="c3p0.acquire_increment">2</property> <property name="c3p0.idle_test_period">2000</property> <property name="c3p0.timeout">2000</property> <property name="c3p0.max_statements">10</property> <!-- 設定 JDBC 的 Statement 讀取數據的時候每次從數據庫中取出的記錄條數 --> <property name="hibernate.jdbc.fetch_size">100</property> <!-- 設定對數據庫進行批量刪除,批量更新和批量插入的時候的批次大小 --> <property name="jdbc.batch_size">30</property> <!-- 指定關聯的map映射 --> <mapping resource="com/shma/hibernate/entity/User.hbm.xml"/> <mapping resource="com/shma/hibernate/entity/Worker.hbm.xml"/> </session-factory> </hibernate-configuration>
2)建立持久化層實體類
緩存
package com.shma.hibernate.entity; import java.sql.Blob; import java.util.Date; public class User { private Integer id; private String name; private Integer age; private Date date; private String oldContent; private Blob image; private String desc; public User() { super(); } public User(String name, Integer age, Date date) { super(); this.name = name; this.age = age; this.date = date; } 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getOldContent() { return oldContent; } public void setOldContent(String oldContent) { this.oldContent = oldContent; } public Blob getImage() { return image; } public void setImage(Blob image) { this.image = image; } } package com.shma.hibernate.entity; public class Worker { private int id; private String name; private Pay pay; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Pay getPay() { return pay; } public void setPay(Pay pay) { this.pay = pay; } } package com.shma.hibernate.entity; public class Pay { private double monthPay; private double yearPay; private int yearDay; private Worker worker; public double getMonthPay() { return monthPay; } public void setMonthPay(double monthPay) { this.monthPay = monthPay; } public double getYearPay() { return yearPay; } public void setYearPay(double yearPay) { this.yearPay = yearPay; } public int getYearDay() { return yearDay; } public void setYearDay(int yearDay) { this.yearDay = yearDay; } public Worker getWorker() { return worker; } public void setWorker(Worker worker) { this.worker = worker; } }
3)建立對象-關係映射文件
安全
<?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="com.shma.hibernate.entity"> <!-- class: 1)dynamic-insert:默認爲false,若是設置爲true,則表示保存一個insert時,動態生成sql語句,僅保存字段不能爲空的值 2)dynamic-update:默認爲false,若是設置爲true,則表示更新一個update時,動態生成sql語句,僅更新修改的字段值 3)select-before-update:在執行update以前,是否執行一次查詢,默認爲false --> <class name="User" table="USER" select-before-update="true" dynamic-insert="true"> <!-- id: unsaved-value:表示持久化對象的oid若是爲該屬性值20,則認爲是一個臨時對象,執行保存操做 type:能夠爲java類型,也能夠設置爲hibernate類型 class:設置持久化類設置惟一標識符方式 increment:由hibernate先執行查詢max,再+1,併發下不安全 identity:底層數據庫自增,底層數據庫必須設置爲自增,適用於mysql、sqlserver sequence:底層數據庫提供序列生成惟一標識符,如oracle hilo:hibernate生成組件,在數據庫建立一張表,讀取並修改該表保存自增 native:經常使用,自動識別使用identity、sequence、hilo --> <id name="id" type="java.lang.Integer" unsaved-value="20"> <column name="ID" /> <generator class="native" /> </id> <!-- property: 1) access:制定hibernate默認屬性訪問策略,默認爲property,調用getter和setter方法,若設置爲field,則經過反射訪問 2) unique:設置屬性惟一值 3) index:設置索引 4) length: 設置字段長度 5) scale: 當字段爲double或float類型時,指定小數點後保留位數 6) formula: 派生屬性,sql表達式,用()括起來 --> <property name="name" type="java.lang.String" access="property" unique="true" index="user_index" length="20"> <column name="NAME" /> </property> <property name="age" type="java.lang.Integer" index="user_index"> <column name="AGE" /> </property> <!-- 在 Java 中, 表明時間和日期的類型包括: java.util.Date 和 java.util.Calendar. 此外, 在 JDBC API 中還提供了 3 個擴展了 java.util.Date 類的子類: java.sql.Date, java.sql.Time 和 java.sql.Timestamp, 這三個類分別和標準 SQL 類型中的 DATE, TIME 和 TIMESTAMP 類型對 應在標準 SQL 中, DATE 類型表示日期, TIME 類型表示時間, TIMESTAMP 類型表示時間戳, 同時包含日期和時間信息 --> <property name="date" type="timestamp"> <column name="DATE" /> </property> <property name="desc" formula="(select concat(name,',',date) from user t where t.id = id)"></property> <!-- 映射大對象 --> <property name="oldContent"> <column name="OLD_CONTENT" sql-type="text"></column> </property> <!-- mysql數據庫不支持 <property name="realContent"> <column name="real_Content" sql-type="clob"></column> </property> --> <property name="image"> <column name="image" sql-type="blob"></column> </property> </class> </hibernate-mapping>
4)經過Hibernate API編程訪問操做數據庫代碼session
package com.shma.hibernate.entity; import java.sql.Date; import java.text.ParseException; import java.text.SimpleDateFormat; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.Test; public class UserTest { @Test public void test() { //1) 建立一個SessionFactory對象 SessionFactory sessionFactory = null; //建立Configuration配置對象,加載hibernate基本配置文件和關係對象映射文件 Configuration configuration = new Configuration().configure(); //棄用 // sessionFactory = configuration.buildSessionFactory(); //建立ServiceRegistry服務註冊對象,hibernate任何配置和服務都須要在這個對象中註冊後才能夠使用 ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() .applySettings(configuration.getProperties()) .buildServiceRegistry(); try { sessionFactory = configuration.buildSessionFactory(serviceRegistry); } catch (Exception e) { e.printStackTrace(); } //2) 建立一個Session對象 Session session = sessionFactory.openSession(); //3) 開啓事務 Transaction transaction = session.beginTransaction(); //4) 執行相關操做 User user = null; try { user = new User("馬韶華", 23, new Date(new SimpleDateFormat("yyyy-MM-dd").parse("1989-11-10").getTime())); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } session.save(user); //5) 提交事務 transaction.commit(); //6) 關閉Session對象 session.close(); //7) 關閉SessionFactroy對象 sessionFactory.close(); } }
三、Session併發
1)session接口是hibernate向引用程序提供的操做數據庫的最主要的接口,提供了基本的增刪改和加載java對象的操做;oracle
2)session具備一個緩存,被稱之爲hibernate一級緩存;位於緩存中的對象稱之爲持久化對象;
package com.shma.hibernate.entity; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class UserTest { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } /** * clear(): 清理緩存 */ @Test public void clear() { User user = (User) session.get(User.class, 1); System.out.println(user); User user2 = (User) session.get(User.class, 1); System.out.println(user2); session.clear(); User user3 = (User) session.get(User.class, 1); System.out.println(user3); } /** * reflesh():會強制發送 SELECT 語句, 以使 Session 緩存中對象的狀態和數據表中對應的記錄保持一致!使數據庫中的記錄同步到session緩存中 */ @Test public void reflesh() { User user = (User) session.get(User.class, 1); System.out.println(user); session.refresh(user); System.out.println(user); } /** * flush(): 使session緩存中的數據同步到數據庫中,爲了保存一致,可能會發送對應的SQL語句操做 * * flush()被調用的契機: * 1) 手動調用session.flush()方法 * 2) 在Transaction對象提交事務以前,會先調用session對象的flush()方法,在提交事務 * 3) 執行HQL或者QBC查詢時,若是緩存中持久化對象屬性發生變化,則會先flush()一次,以保證查詢出來的是最新的數據 * 4) 若是持久化對象主鍵採用native生成OID(記錄的 ID 是由底層數據庫使用自增的方式生成),在調用save()方法時,先發生insert()語句,以建立主鍵id,保證save()方法後主鍵id是存在的 */ @Test public void testSessionFlush() { // User user = (User) session.get(User.class, 1); // user.setAge(27); // user.setName("齊嬌嬌"); // // session.flush(); //將session緩存中的數據同步到數據庫中,執行update方法,可是數據庫值沒有修改,沒有commit // System.out.println(user); // User user = (User) session.get(User.class, 1); // // //執行HQL或者QBC查詢時,若是緩存中持久化對象屬性發生變化,則會先flush()一次,以保證查詢出來的是最新的數據 // User user2 = (User) session.createCriteria(User.class).uniqueResult(); // // System.out.println(user == user2); User user3 = new User("孫威", 28, new Date()); session.save(user3); } /** * 驗證session緩存 */ @Test public void testSessionCache() { User user = (User) session.get(User.class, 1); System.out.println(user); User user2 = (User) session.get(User.class, 1); //從session緩存中獲取,沒有查詢數據庫 System.out.println(user2); System.out.println(user == user2); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } }
四、持久化對象狀態
1)站在持久化的角度上,hibernate將對象分爲四種狀態:
持久化狀態:存在session緩存中,存在數據庫記錄中,存在OID
臨時狀態:不存在session緩存中,不存在數據庫記錄中,不存在OID
遊離狀態:存在OID,不存在session緩存中,可能存在數據庫記錄中,通常狀況下游離對象是由持久化對象轉變而來
刪除狀態:存在OID,可是數據庫中不存在對應的記錄,不存在數據庫中,不存在session緩存中
package com.shma.hibernate.entity; import java.sql.Connection; import java.sql.SQLException; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.jdbc.Work; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class UserTest2 { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; /** * 調用存儲過程 */ @Test public void testDoWork() { session.doWork(new Work() { @Override public void execute(Connection conn) throws SQLException { //調用存儲過程 } }); } /** * evict():從緩存中移除指定的持久化對象 */ @Test public void testEvict() { User user = (User) session.get(User.class, 8); User user2 = (User) session.get(User.class, 9); user.setName("nihao"); user2.setName("haha"); session.evict(user); } /** * delete: 執行刪除操做. 只要 OID 和數據表中一條記錄對應, 就會準備執行 delete 操做 * 若 OID 在數據表中沒有對應的記錄, 則拋出異常 * * 能夠經過設置 hibernate 配置文件 hibernate.use_identifier_rollback 爲 true, * 使刪除對象後, 把其 OID 置爲 null */ @Test public void testDelete() { // User user = new User(); // user.setId(1); // session.delete(user); User user = (User) session.get(User.class, 3); session.delete(user); System.out.println(user); } /** * saveOrUpdate: * 包含了save和update方法,當對象處於遊離狀態時,則執行save操做,當對象處於持久化狀態時,則執行update操做 * 判斷是否爲臨時狀態: * 一、Java對象的OID爲null * 二、若是OID在數據庫表記錄中不存在,則會拋出異常, * 除非映射文件中<id>設置了unsaved-value屬性,而且java對象中的oid值與設置的unsaved-value值一致 */ @Test public void testSaveOrUpdate() { // User user = new User("王二", 22, new Date()); // // //user處於遊離狀態,執行save // session.saveOrUpdate(user); // // // 執行save操做後user轉變爲持久化對象 // user.setAge(45); // user.setName("王五"); // // session.saveOrUpdate(user); User user2 = new User("aidai", 10, new Date()); user2.setId(999); session.saveOrUpdate(user2); } /** * update(): * 1) 若更新一個持久化對象,不須要顯示調用update方法,由於在調用Transaction的commit方法 * 時,會調用session的flush()方法 * * 2) 若更新一個遊離對象,須要顯示的調用update方法,把一個遊離對象轉換爲持久化對象 * * 須要注意的地方: * 一、不管要更新的遊離對象和數據庫表中的記錄是否一致(持久化對象會先檢查,不一致才執行update),都會調用update * 操做,如何能讓 update方法再也不盲目的出發 update 語句呢 ? 在 .hbm.xml 文件的 class 節點設置 * select-before-update=true (默認爲 false). 這個屬性的含義是在每次update以前先查詢一遍數 * 據庫,若是有修改在執行update,但一般不須要設置該屬性. * * 二、若數據表中沒有對應的記錄, 但還調用了 update 方法, 會拋出異常 * * 三、當 update() 方法關聯一個遊離對象時, * 若是在 Session 的緩存中已經存在相同 OID 的持久化對象, 會拋出異常. 由於在 Session 緩存中 * 不能有兩個 OID 相同的對象! */ @Test public void testUpdate() { // 持久化對象,不須要顯示調用update方法 User user = (User) session.get(User.class, 1); // user.setName("齊嬌嬌"); // session.update(user); // session.clear(); // 遊離狀態,必須顯示調用update方法 // user.setName("馬韶華"); // session.update(user); User user2 = (User) session.get(User.class, 1); session.update(user); //session 中已經存在user2 } @Before public void init() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } /** * 1) 執行get()方法:當即執行查詢操做加載對象,get爲當即檢索 * 執行load()方法:如不使用該對象,則不會執行查詢操做,而是返回一個代理對象,load爲延遲檢索 * 2) 當使用load延時檢索時,若是session關閉,可能會拋出LazyInitializationException異常 * 3) 若是查詢的oid數據庫沒有對應的數據記錄,而且session也沒有關閉 * get方法返回null * load方法若是不使用實體對象屬性,加載不會拋出異常,使用的時候會拋出異常 * */ @Test public void testLoad() { User user = (User) session.load(User.class, 10); System.out.println(user.getClass().getName()); // session.close(); System.out.println(user); } /** * get/load:根據一個oid,從數據庫中加載一個持久化對象到session緩存中 */ @Test public void testGet() { User user = (User) session.get(User.class, 10); System.out.println(user.getClass().getName()); // session.close(); System.out.println(user); } /** * persist(): 和save方法同樣保存記錄到持久化對象 * 和save()方法區別:當對一個OID不爲null的對象執行save時,會把對象以一個新oid保存到數據庫中,而persist則會拋出異常 */ @Test public void testPersist() { User user = new User(); user.setAge(20); user.setDate(new Date()); user.setName("zhangsan"); user.setId(10); // 拋出異常 session.persist(user); } /** * save():用於將臨時對象轉換爲持久化對象,插入記錄 * 執行步驟:1) 使一個臨時對象保存到session緩存中,轉換爲持久化對象 * 2) 爲持久化對象生成惟一的UID * 3) 執行一條insert語句:在flush緩存時 * 4) 在save以前的設置id是無效的 * 5) 在save以後的設置id是不能被修改的,修改會拋出異常 */ @Test public void testSave() { User user = new User(); user.setAge(20); user.setDate(new Date()); user.setName("zhangsan"); // user.setId(10); // 設置id是無效的 session.save(user); System.out.println(user); user.setId(10); //save()後修改id,拋出異常 } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } @Test public void testWorker() { Worker worker = new Worker(); Pay pay = new Pay(); pay.setMonthPay(13000.23d); pay.setYearDay(5); pay.setYearPay(153422.12344d); worker.setName("馬韶華"); worker.setPay(pay); session.save(worker); } }
五、映射對象關係
1)單向多對一
package com.shma.hibernate.entity.n21; public class Customer { private int customerId; private String customerName; public int getCustomerId() { return customerId; } public void setCustomerId(int customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } @Override public String toString() { return "Customer [customerId=" + customerId + ", customerName=" + customerName + "]"; } } package com.shma.hibernate.entity.n21; public class Order { private int orderId; private String orderName; private Customer customer; public int getOrderId() { return orderId; } public void setOrderId(int orderId) { this.orderId = orderId; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } @Override public String toString() { return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]"; } } package com.shma.hibernate.entity.n21; import static org.junit.Assert.*; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestN21 { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } @Test public void testMany2OneDel() { // Order order = (Order)session.get(Order.class, 2); // session.delete(order); // // session.delete(order.getCustomer()); //在不設定級聯關係的狀況下, 且 1 這一端的對象有 n 的對象在引用, 不能直接刪除 1 這一端的對象 Customer customer = (Customer) session.get(Customer.class, 2); session.delete(customer); } @Test public void testMany2OneUpdate() { Order order = (Order)session.get(Order.class, 1); order.setOrderName("order-112222"); order.getCustomer().setCustomerName("AAAAAAAA"); } @Test public void testMany2OneGet() { Order order = (Order)session.get(Order.class, 1); System.out.println(order); System.out.println(order.getCustomer().getClass()); //若是session被關閉,將拋出異常 // session.close(); //延時加載Customer Customer customer = order.getCustomer(); System.out.println(customer); System.out.println(customer.getClass()); } @Test public void testMany2OneSave() { // Customer customer = new Customer(); // customer.setCustomerName("AAA"); // // Order order01 = new Order(); // order01.setOrderName("Order-01"); // // Order order02 = new Order(); // order02.setOrderName("Order-02"); // // order01.setCustomer(customer); // order02.setCustomer(customer); // // //先savecustomer,會saveorder,執行三次insert // session.save(customer); // session.save(order01); // session.save(order02); Customer customer = new Customer(); customer.setCustomerName("BBB"); Order order01 = new Order(); order01.setOrderName("Order-03"); Order order02 = new Order(); order02.setOrderName("Order-04"); order01.setCustomer(customer); order02.setCustomer(customer); //先save order,會save customer,執行三次insert,會執行2次update session.save(order01); session.save(order02); session.save(customer); } }
<?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="com.shma.hibernate.entity.n21.Customer" table="CUSTOMERS"> <id name="customerId" type="int"> <column name="CUSTOMER_ID" /> <generator class="native" /> </id> <property name="customerName" type="java.lang.String"> <column name="CUSTOMER_NAME" /> </property> </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"> <!-- Generated 2015-7-18 15:21:35 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping package="com.shma.hibernate.entity.n21"> <class name="Order" table="ORDERS"> <id name="orderId" type="int"> <column name="ORDER_ID" /> <generator class="native" /> </id> <property name="orderName" type="java.lang.String"> <column name="ORDER_NAME" /> </property> <!-- 多對一映射關係 name:多這一端的一那一端的屬性名稱 class:一端的類型 column:一那一端對應在多端的外鍵名稱 --> <many-to-one name="customer" class="Customer"> <column name="customer_id"></column> </many-to-one> </class> </hibernate-mapping>
2)雙向一對多
package com.shma.hibernate.entity.n21.bath; import java.util.HashSet; import java.util.Set; public class Customer { private int customerId; private String customerName; /** * 一、聲明集合須要使用接口,由於hibernate延遲加載,在獲取集合的時候是獲取到的hibernate內部集合實例 * 二、須要把集合進行初始化, 能夠防止發生空指針異常 */ private Set<Order> orders = new HashSet<>(); public int getCustomerId() { return customerId; } public void setCustomerId(int customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } } package com.shma.hibernate.entity.n21.bath; public class Order { private int orderId; private String orderName; private Customer customer; public int getOrderId() { return orderId; } public void setOrderId(int orderId) { this.orderId = orderId; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } @Override public String toString() { return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]"; } } package com.shma.hibernate.entity.n21.bath; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class Test12N { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } @Test public void testOne2ManyDel() { //在不設定級聯關係的狀況下, 且 1 這一端的對象有 n 的對象在引用, 不能直接刪除 1 這一端的對象 Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer.getOrders().iterator().next()); } @Test public void testOne2ManyUpdate() { Customer customer = (Customer) session.get(Customer.class, 1); customer.setCustomerName("CCCCCC"); Customer customer2 = (Customer) session.get(Customer.class, 2); customer.getOrders().iterator().next().setCustomer(customer2); } @Test public void testOne2ManyGet() { Customer customer = (Customer) session.get(Customer.class, 1); System.out.println(customer.getCustomerName()); //延時加載 //返回的多的一端的集合時 Hibernate 內置的集合類型. //該類型具備延遲加載和存放代理對象的功能. System.out.println(customer.getOrders().getClass()); //3. 可能會拋出 LazyInitializationException 異常 // session.close(); System.out.println(customer.getOrders().iterator().next().getOrderName()); //再須要使用集合中元素的時候進行初始化. } @Test public void testOne2ManySave() { // Customer customer = new Customer(); // customer.setCustomerName("AAA"); // // Order order01 = new Order(); // order01.setOrderName("Order-01"); // // Order order02 = new Order(); // order02.setOrderName("Order-02"); // // order01.setCustomer(customer); // order02.setCustomer(customer); // // customer.getOrders().add(order01); // customer.getOrders().add(order02); // // //先savecustomer,會saveorder,執行三次insert // session.save(customer); // session.save(order01); // session.save(order02); Customer customer = new Customer(); customer.setCustomerName("BBB"); Order order01 = new Order(); order01.setOrderName("Order-03"); Order order02 = new Order(); order02.setOrderName("Order-04"); order01.setCustomer(customer); order02.setCustomer(customer); customer.getOrders().add(order01); customer.getOrders().add(order02); //先save order,會save customer,執行三次insert,會執行2次update session.save(order01); session.save(order02); session.save(customer); } }
<?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="com.shma.hibernate.entity.n21.bath"> <class name="Customer" table="CUSTOMERS"> <id name="customerId" type="int"> <column name="CUSTOMER_ID" /> <generator class="native" /> </id> <property name="customerName" type="java.lang.String"> <column name="CUSTOMER_NAME" /> </property> <!-- 1對多映射關係那個屬性集合 set:映射集合爲set類型 table:set中集合類型的所對應的表名,須要與多對一中的表名一致 inverse:指定由哪一方來維護關聯關係. 一般設置爲 true, 以指定由多的一端來維護關聯關係 cascade:級聯操做,save-update級聯保存並修改關聯,delete:級聯刪除 order-by:排序,字段是數據庫裏面的字段類型 name:1的集合屬性名稱 --> <set name="orders" table="ORDERS" inverse="true" order-by="order_name desc"> <!-- 執行多的表中的外鍵列的名字 --> <key column="CUSTOMER_ID"></key> <!-- 指定映射類型 --> <one-to-many class="Order"/> </set> </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"> <!-- Generated 2015-7-18 15:21:35 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping package="com.shma.hibernate.entity.n21.bath"> <class name="Order" table="ORDERS"> <id name="orderId" type="int"> <column name="ORDER_ID" /> <generator class="native" /> </id> <property name="orderName" type="java.lang.String"> <column name="ORDER_NAME" /> </property> <!-- 多對一映射關係 name:多這一端的一那一端的屬性名稱 class:一端的類型 column:一那一端對應在多端的外鍵名稱 --> <many-to-one name="customer" class="Customer"> <column name="customer_id"></column> </many-to-one> </class> </hibernate-mapping>