接上篇《hibernate 映射 set 值對象 簡單映射》
如果我們允許用戶不停的添加同一工作到user中改如何處理?
允許重複元素的無序集合稱爲包(bag),javaCollections框架並沒有具體的實現,僅有此集合的語義定義,因此需要一種匹配的實現。
可以有兩種做法
1、用java.util.Collection接口編寫集合屬性,並在聲明中用jak的一個ArrayList對其初始化,在hibernate中用<bag><idbag>元素映射即可。Hibernate有一個內建的PersistentBag可以處理列表;但與包的預定一致,它忽略元素在ArrayList中的位置。也就是說你得到了一個持久化的Collection.
2、用java.util.List接口編寫屬性即可,並在聲明中用JDK的一個ArrayList把它初始化,像像前面一樣去映射他,但是在領域模型類中公開了一個不同的集合接口。這樣很有效,但不建議使用,因爲使用這個集合屬性的客戶端可能認爲元素的順序會始終被保存,其實如果把它作爲<bag>或<idbag>映射,就並非如此。
建議使用第一個選項。
由於我們需要存儲不同的task,表必須需要一個不同的主鍵而<idbag>映射添加了一個黛綠列到集合表,很像用於實體的合成標示符;
修改的User類如下:
package com.ccay.test.valueCollection.idbag.xml;
import java.util.ArrayList;
import java.util.Collection;
public class User {
private long userId;
private String firstname;
private String lastname;
private Collection<String> tasks = new ArrayList<String>();
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public Collection<String> getTasks() {
return tasks;
}
public void setTasks(Collection<String> tasks) {
this.tasks = tasks;
}
}
xml文件如下
<?xml version="1.0" encoding="utf-8"?>
<!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.ccay.test.valueCollection.idbag.xml.User" table="VAL_COLLECTION_SIMPLE_SET_USER" >
<id name="userId" type="long">
<column name="USER_ID"/>
<generator class="native" />
</id>
<property name="firstname" type="string">
<column name="FIRSTNAME" length="40" />
</property>
<property name="lastname" type="string">
<column name="LASTNAME" length="50" />
</property>
<idbag name="tasks" table="VAL_COLLECTION_SIMPLE_SET_TASKS">
<collection-id type="long" column="USER_TASK_ID">
<!-- 注意這裏的主鍵生成策略不同於user,當指定native後會報錯具體原因未找到 -->
<generator class="increment"/>
</collection-id>
<key column="USER_ID"/>
<element type="string" column="TASK" not-null="true"></element>
</idbag>
</class>
</hibernate-mapping>
測試類
package com.ccay.test.valueCollection.idbag.xml;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.ccay.test.HibernateSessionFactory;
public class Test {
@org.junit.Test
public void testDDL(){
Session session = HibernateSessionFactory.getSession();
Transaction transaction = session.beginTransaction();
ArrayList<String> tasks = new ArrayList<String>();
tasks.add("student");
tasks.add("student");
tasks.add("student");
tasks.add("student");
User user= new User();
user.setFirstname("firstName");
user.setLastname("lastName");
//雖然此方法接收所有實現Collection的接口,但最好使用ArratList,hibernate內部也是將其轉換爲ArrayList了。
user.setTasks(tasks);
session.save(user);
transaction.commit();
HibernateSessionFactory.closeSession();
}
}
自動ddl如下
create table VAL_COLLECTION_SIMPLE_SET_TASKS (
USER_ID bigint not null,
TASK varchar(255) not null,
USER_TASK_ID bigint not null,
primary key (USER_TASK_ID)
)
create table VAL_COLLECTION_SIMPLE_SET_USER (
USER_ID bigint not null auto_increment,
FIRSTNAME varchar(40),
LASTNAME varchar(50),
primary key (USER_ID)
)
alter table VAL_COLLECTION_SIMPLE_SET_TASKS
add index FK839C9A2737A11A64 (USER_ID),
add constraint FK839C9A2737A11A64
foreign key (USER_ID)
references VAL_COLLECTION_SIMPLE_SET_USER (USER_ID)
方向工程