??xml version="1.0" encoding="utf-8" standalone="yes"?> ?/span> 多對一 ?/span>一多 中都是單向關聯,也就是其中一斚w聯到另一方,而另一方不知道自己被關聯?/span> package onlyfun.caterpillar; package onlyfun.caterpillar; <?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?> User user1 = new User(); User user1 = new User(); Hibernate: insert into room (address) values (?) <?xml version="1.0" encoding="utf-8"?> User user1 = new User(); Hibernate: insert into room (address) values (?)
其核心在于批量插入时Q积攒一定量后就写库Qƈ清除SESSION里的W一U缓存,以免后箋插入操作受缓存查找而媄响效率:
session.flush();
session.clear();
}
ZJPA的事务操作,SESSION不可见,此时Q需要直接调用EntityManager的flush和clear?br />
但EntityManager也是被封装入JpaDaoSupportQ实际的EntityManager对象也不Ҏ(gu)取得?br />
此时可以用其JpaTemplate成员的executeҎ(gu)来实现这两个操作Q?br />
public Object doInJpa(EntityManager em) throws PersistenceException {
em.flush();
em.clear();
return null;
}
}, true);
在我q里试l果Q?br />
没有定期调用以上Ҏ(gu)Ӟ插入50个记录要2U,q且随着记录增多Q时间越来越ѝ?br />
每插?0个调用以上方法后Q插?0个记录小?00毫秒Q且不随记录个数U性增ѝ?br />
]]>
]]>
在PD的OOM中双M条关p连U,讄NavigateQ这h会在各自hbm.xml中生成many-to-one及one-to-many关系?br>
另外Q根?#8220;附文”的效率说明还需要设|:由多方DISKl护关系Qƈ且当HOST更新Ӟ也要更新DISK?br>
生成的HBM.XML如下Q?br>HOST的:
<joined-subclass name="Host" table="host" dynamic-update="false" dynamic-insert="false" select-before-update="false" lazy="true" abstract="false">
<key on-delete="noaction" unique="true">
<column name="dev_id" sql-type="int" not-null="true" length="0"/>
</key>
<array name="nic" optimistic-lock="true">
<key on-delete="noaction" unique="true">
<column name="dev_id" sql-type="int" not-null="false" length="0"/>
</key>
<list-index column="IndexColumnB"/>
<one-to-many class="eb.nms.db.Nic"/>
</array>
<set name="disk" outer-join="false" inverse="true" lazy="true" optimistic-lock="true" cascade="save-update">
<key on-delete="noaction" unique="true">
<column name="dev_id" sql-type="int" not-null="false" length="0"/>
</key>
<one-to-many class="eb.nms.db.Disk"/>
</set>
</joined-subclass>
DISK的:
<class name="Disk" table="disk" mutable="true" lazy="true" abstract="false">
<id name="diskId">
<column name="disk_id" sql-type="int" not-null="true"/>
<generator class="native">
</generator>
</id>
<property name="diskName" insert="true" update="true" optimistic-lock="true">
<column name="disk_name" sql-type="varchar(254)" length="254"/>
</property>
<many-to-one name="host" class="Host" outer-join="false" update="true" insert="true">
<column name="dev_id" sql-type="int" not-null="false" length="0"/>
</many-to-one>
</class>
附文Q?br>
如果讓雙斚w意識到另一方的存在Q這就形成了雙向關聯,在多一、一多的例子可以改寫一下,重新a計User別如下Q?/span>
public class User {
private Integer id;
private String name;
private Room room;
public User() {}
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 Room getRoom() {
return room;
}
public void setRoom(Room room) {
this.room = room;
}
}
Room別如下Q?/span>
import java.util.Set;
public class Room {
private Integer id;
private String address;
private Set users;
public Room() {}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Set getUsers() {
return users;
}
public void setUsers(Set users) {
this.users = users;
}
public void addUser(User user) {
users.add(user);
}
public void removeUser(User user) {
users.remove(user);
}
}
如此Q?/span>User實例可參考至Room實例而維持多一關係Q?/span>Room實例a得User實例而維持一多關係?/span>
在映文件方面,可以如下撰寫Q?/span>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="onlyfun.caterpillar.User" table="user">
<id name="id" column="id" type="java.lang.Integer">
<generator class="native"/>
</id>
<property name="name" column="name" type="java.lang.String"/>
<many-to-one name="room"
column="room_id"
class="onlyfun.caterpillar.Room"
cascade="save-update"
outer-join="true"/>
</class>
</hibernate-mapping>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="onlyfun.caterpillar.Room" table="room">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="address"
column="address"
type="java.lang.String"/>
<set name="users" table="user" cascade="save-update">
<key column="room_id"/>
<one-to-many class="onlyfun.caterpillar.User"/>
</set>
</class>
</hibernate-mapping>
映射文g雙方都設定了cascade?/span>save-updateQ所以?zhn)可以用多一的方式來E持關聯Q?/span>
user1.setName("bush");
User user2 = new User();
user2.setName("caterpillar");
Room room1 = new Room();
room1.setAddress("NTU-M8-419");
user1.setRoom(room1);
user2.setRoom(room1);
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(user1);
session.save(user2);
tx.commit();
session.close();
或是反過來由一多的方式來E持關聯Q?/span>
user1.setName("bush");
User user2 = new User();
user2.setName("caterpillar");
Room room1 = new Room();
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-419");
room1.addUser(user1);
room1.addUser(user2);
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(room1);
tx.commit();
session.close();
這邊有個效率議可以探a,上面的程式片D?/span>Hibernate用以下的SQL進行儲存Q?/span>
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: update user set room_id=? where id=?
Hibernate: update user set room_id=? where id=?
上面的程式寫法表C關聯由Room單方面維持,而主控方也是RoomQ?/span>User不知?/span>Room?/span>room_id是多,所以必須分別儲?/span>Room?/span> User之後Q再更新user?/span>room_id?/span>
在一多、多一形成雙向關聯的情況下Q可以將關聯E持的控制權交多的一方,這樣會比較有效率Q理׃難理解,像是在公司中,老闆要記住多個員工的姓名快,還是每一個員工都a得老闆的姓名快?/span>
所以在一多、多一形成雙向關聯的情況下Q可以在「一」的一方設定控制權反轉Q也是當儲存「一」的一Ҏ(gu)Q將關聯E持的控制權交「多」的一方,以上面的例子來說Q可以設?/span>Room.hbm.xml如下Q?/span>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="onlyfun.caterpillar.Room" table="room">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="address"
column="address"
type="java.lang.String"/>
<set name="users" table="user" cascade="save-update" inverse="true">
<key column="room_id"/>
<one-to-many class="onlyfun.caterpillar.User"/>
</set>
</class>
</hibernate-mapping>
由於關聯的控制權交「多」的一方了Q所以直接儲存「一」方前,「多」的一方必須意識到「一」的存在Q所以程式片D必須改為如下:
user1.setName("bush");
User user2 = new User();
user2.setName("caterpillar");
Room room1 = new Room();
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-419");
room1.addUser(user1);
room1.addUser(user2);
// 多方必須意識到單方的存在
user1.setRoom(room1);
user2.setRoom(room1);
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(room1);
tx.commit();
session.close();
上面的程式片D?/span>Hibernate用以下的SQLQ?/span>
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: insert into user (name, room_id) values (?, ?)
如果控制Ɗ交i另一方了Q而另一Ҏ(gu)有意識到方的存在的話會如何Q試著將上面的程式片D中user1.setRoom(room1);?/span> user2.setRoom(room1);UdQ執行之後,(zhn)會發現資料庫中room_id會出?/span>null|這種i果好比在 多對一 中,(zhn)沒有分配User一?/span>RoomQ理所當然的,room_id會出?/span>null?/span>
]]>