2012-12-14 28 views
4

我:保存多對多集合使用無狀態會話

@Entity 
public class EmailAndName { 
... 
} 

@Entity 
public class MessageDetails { 
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    @JoinTable(name = "MessageDetails_to") 
    public Set<EmailAndName> getTo() { 
     return to; 
    } 
} 

不填充我

public static void main(String []a) 
{ 
    StatelessSession sess = HibernateUtils.getSessionFactory().openStatelessSession(); 
    sess.beginTransaction(); 
    MessageDetails messageDetails = new MessageDetails(); 
    messageDetails.setTo(new HashSet<EmailAndName>()); 
    EmailAndName emailAndName = (EmailAndName) sess.get(EmailAndName.class, 1L); 
    if (emailAndName == null) throw new RuntimeException(); 
    messageDetails.getTo().add(emailAndName); 
    sess.insert(messageDetails); 
    sess.getTransaction().commit(); 
} 

MessageDetails_to表時。我該怎麼辦?我不想編寫原生查詢。謝謝。

+0

能詳細提供表結構? –

+0

我知道你說過你不想寫本地查詢,但是我發現在無狀態會話中填充多對多關聯表的唯一方法(從而從無狀態會話的速度中受益)。即'sess.CreateSQLQuery(「插入到MessageDetails_to(...)值(:id1,id2).SetParameter ...等」 –

回答

5

您還沒有通過hibernate-doc閱讀無狀態會話

它明確指出:

Operations performed using a stateless session never cascade to associated instances. Collections are ignored by a stateless session. 

而你嘗試添加Set<EmailAndName>。無狀態會話是較低層次的抽象,更接近底層的JDBC。所以如果你真的想讓你的代碼工作並填充MessageDetails_to ..你需要去Session。你需要定義你的POJO的的equals和hashCode方法:)

讓你修改後的代碼將是:

public static void main(String []a) 
{ 
    try{ 
    Session sess = HibernateUtils.getSessionFactory().openSession(); 
    sess.beginTransaction(); 
    MessageDetails messageDetails = new MessageDetails(); 
    messageDetails.setTo(new HashSet<EmailAndName>()); 
    EmailAndName emailAndName = (EmailAndName) sess.get(EmailAndName.class, 1L); 
    if (emailAndName == null) throw new RuntimeException(); 
    messageDetails.getTo().add(emailAndName); 
    sess.save(messageDetails); 
    sess.getTransaction().commit(); 
} 
catch(HibernateException e) 
{ 
    sess.getTransaction.rollback(); 
    e.printStackTrace(); 
} 
    finally{ 
     sess.close(); 
    } 

你必須始終有一個嘗試捕捉封閉的,這樣就可以識別出異常(如果有的話),並使其工作:)

0

首先,您確定交易是否已提交?

其次,您正在使用Set。你確定EmailAndName類的equalshashCode方法是否定義良好?

+0

我承諾我使用無狀態會話,這就是爲什麼不需要實現散列和等於 –

+0

您使用的會話類型與您的模型對象是否需要equals和hashCode有什麼關係? – Marvo

+0

「Set」確實需要一個equals和一個hashCode方法,如果沒有這些,它將無法工作。 –

0

嗯,我認爲你的代碼不工作的主要原因是由於使用無狀態會話,但無論如何我會建議你,當你實現1- N和NM關係定義關係的反面並更新雙方。

另外,不要讓外部類直接操作一個集合,因爲它打破了封裝。不要爲集合公開set方法,它可能會導致非常惡劣的異常很難調試。使用刪除方法來更新您的設置。

@Entity 
public class MessageDetails { 

    private Set<EmailAndName> to = new HashSet<EmailAndName>(); 

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    @JoinTable(name = "MessageDetails_to", 
     joinColumns = {@JoinColumn(name = "MESSAGE_DETAILS_ID"}, 
     inverseJoinColumns = {@JoinColumn(name = "EMAIL_AND_ADDRESS_ID")}) 
    public Set<EmailAndName> getTo() { 
     return Collections.unmodifiableSet(to); 
    } 

    public void addEmaiAndName(EmailAndName emailAndName) { 
     emailAndName.setMessageDetails(this); 
     to.add(emailAndName); 
    } 

    public void removeEmailAndName(EmailAndName emailAndName) { 
     emailAndName.setMessageDetails(null); 
     to.remove(emailAndName); 
    } 

} 

代碼的其他部分應該是這樣的:

Session sess = HibernateUtils.getSessionFactory().openSession(); 
sess.beginTransaction(); 
MessageDetails messageDetails = new MessageDetails(); 
EmailAndName emailAndName = (EmailAndName) sess.get(EmailAndName.class, 1L); 
if (emailAndName == null) throw new RuntimeException(); 
messageDetails.addEmailAndName(emailAndName); 
sess.save(messageDetails); 
sess.getTransaction().commit();