Hibernate學習之一對多關聯
注意事項:
1.單向一對多
只需在“一”放進行配置
2.雙向一對多
需要在關聯雙方都加以配置,而且需要在一的一方設置inverse=true
首先是實體類:
TAddress.java(多的一方)
public class TAddress implements Serializable { private static final long serialVersionUID = 1121137857691229229L; private Integer id; private String address; private String zipcode; private String tel; private String type; private TUser user; //必須有 ............ }
TUser.java(一的一方)
public class TUser implements Serializable { private static final long serialVersionUID = 1224691192698621789L; private Integer id; private Integer age; private String name; @SuppressWarnings("rawtypes") private Set address = new HashSet(); //多的一方放在集合中
.................... }
然后是各個實體類的配置文件
TAddress.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<!-- 一對多 -->
<hibernate-mapping>
<class name="com.model.TAddress" table="t_address"
dynamic-update="false" dynamic-insert="false">
<id name="id" type="java.lang.Integer" column="id" unsaved-value="0">
<generator class="native" />
</id>
<property name="address" column="address" type="string" />
<property name="tel" column="tel" type="string" />
<property name="zipcode" column="zipcode" type="string" />
<property name="type" column="type" type="string" />
<!-- 必須有many-to-one 否則關聯字段(user_id)為null -->
<many-to-one name="user"
class="com.model.TUser"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="user_id"
not-null="true">
</many-to-one>
</class>
</hibernate-mapping>
TUser.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<!-- 一對多 外鍵關聯 -->
<!-- Select from TUser where id=1 Select from TUser where id=1 to Select
from TUser where id=1 or id=2 -->
<!-- batch-size 批量加載機制 可以自定義每次批量加載的數量 -->
<hibernate-mapping>
<class name="com.model.TUser" table="t_user" dynamic-update="true"
>
<id name="id" type="java.lang.Integer" column="id" unsaved-value="0">
<generator class="native" />
</id>
<property name="name" column="name" />
<property name="age" column="age" />
<set name="address" table="t_address" cascade="all" order-by="zipcode asc"
lazy="true" inverse="true">
<key column="user_id" /><!-- 確定關聯的外鍵列 -->
<one-to-many class="com.model.TAddress" />
</set>
</class>
</hibernate-mapping>
其次是hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- properties -->
<!-- 數據庫URL -->
<property name="hibernate.connection.url">jdbc:mysql://localhost/onetomany</property>
<!-- 數據庫JDBC驅動 -->
<property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
<!-- 數據庫用戶名 -->
<property name="hibernate.connection.username">root</property>
<!-- 數據庫密碼 -->
<property name="hibernate.connection.password">hello</property>
<!-- 數據庫方言 -->
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!-- 是否日志調試 -->
<property name="show_sql">true</property>
<!-- 是否使用數據庫外連接 -->
<property name="use_outer_join">true</property>
<!-- 事務管理 使用JDBC Transaction(使用JTA會報錯) -->
<property name="transaction.factory_class">
net.sf.hibernate.transaction.JDBCTransactionFactory
</property>
<!-- 指定hibernate每次提交的SQL數量 對批量操作的性能提升幫助很大!!!!!!!!!!!!! -->
<property name="hibernate.jdbc.batch_size">25</property>
<!-- 映射文件配置,配置文件名必須包含其相對于根的全路徑 -->
<mapping resource="com/model/TUser.hbm.xml" />
<mapping resource="com/model/TAddress.hbm.xml" />
</session-factory>
</hibernate-configuration>
測試代碼(部分)
增加
public void testSave(){ try { Transaction tx=session.beginTransaction(); // TUser user=(TUser) session.load(TUser.class, 1); TUser user=new TUser(); user.setName("zhangsan"); user.setAge(20); TAddress address=new TAddress(); address.setAddress("jingsan"); address.setTel("1361380"); address.setZipcode("45000"); address.setType("java"); address.setUser(user); //設置關聯的TUser對象 user.getAddress().add(address); session.save(user); //級聯更新 tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } }
查詢
public void testLoad(){ try { Transaction tx=session.beginTransaction(); String hql="from TUser where name='zhangsan'"; List list=session.createQuery(hql).list(); System.out.println("-------------1------------"); Iterator iter=list.iterator(); while(iter.hasNext()){ TUser user=(TUser) iter.next(); System.out.println("--------------2------------"); System.out.println("user.name="+user.getName()); System.out.println("--------------3------------"); System.out.println("user.address="+user.getAddress().size()); System.out.println("--------------4------------"); } } catch (HibernateException e) { e.printStackTrace(); } }
批量插入(可以提高性能)
實現機制:如果使用了批量加載機制,hibernate在進行數據查詢操作前,會自動在當前session中尋找是否還存在
其他同類型待加載的數據,如果有,則將其查詢條件合并在當前的select語句中一并提交,這樣,通過
一次數據庫操作即完成了多個讀取任務。
//批量插入操作性能優化 通過配置<property name="hibernate.jdbc.batch_size">25</property> public void testBatchInsert(){ long start=System.currentTimeMillis(); this.importUserList(); long end=System.currentTimeMillis(); System.out.println("批量插入花費時間是"+(end-start)); } public void importUserList(){ try { Transaction tx=session.beginTransaction(); for(int i=0;i<10000;i++){ TUser user=new TUser(); user.setName("user"+i); session.save(user); if(i%25==0){ //以每25個數據作為一個處理單元 session.flush(); session.clear(); } } tx.commit(); } catch (HibernateException e) { e.printStackTrace(); } }