我对Hibernate不太熟悉,我正在尝试创建一对多映射。
以下是相关表格:
这是我的映射文件:
<hibernate-mapping package="com.xorty.mailclient.server.domain">
<class name="Attachment" table="Attachment">
<id name="id">
<column name="idAttachment"></column>
</id>
<property name="filename">
<column name="name"></column>
</property>
<property name="blob">
<column name="file"></column>
<type name="blob"></type>
</property>
<property name="mailId">
<column name="mail_idmail"></column>
</property>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.xorty.mailclient.server.domain.Mail" table="mail">
<id name="id" type="integer" column="idmail"></id>
<property name="content">
<column name="body"></column>
</property>
<property name="ownerAddress">
<column name="account_address"></column>
</property>
<property name="title">
<column name="head"></column>
</property>
<set name="receivers" table="mail_has_contact" cascade="all">
<key column="mail_idmail"></key>
<many-to-many column="contact_address" class="com.xorty.mailclient.client.domain.Contact"></many-to-many>
</set>
<bag name="attachments" cascade="save-update, delete" inverse="true">
<key column="mail_idmail" not-null="true"/>
<one-to-many class="com.xorty.mailclient.server.domain.Attachment"/>
</bag>
</class>
</hibernate-mapping>
简单来说,一封邮件附件更多。 当我尝试在没有附件的邮件上进行CRUD时,每个工作都很好。当我向邮件添加一些附件时,我无法执行任何CRUD操作。
我最终得到以下追踪:
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at domain.DatabaseTest.testPersistMailWithAttachment(DatabaseTest.java:355)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails (`maildb`.`attachment`, CONSTRAINT `fk_Attachment_mail1` FOREIGN KEY (`mail_idmail`) REFERENCES `mail` (`idmail`) ON DELETE NO ACTION ON UPDATE NO ACTION)
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1666)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1082)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 27 more
谢谢
编辑:关于hvgotcodes提案:
package com.xorty.mailclient.server.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.xorty.mailclient.client.domain.Account;
import com.xorty.mailclient.client.domain.AttachmentDTO;
import com.xorty.mailclient.client.domain.Contact;
import com.xorty.mailclient.client.domain.MailDTO;
/**
* Heavy weight Hibernate Mail
* @author MisoV
* @version 0.1
*/
public class Mail implements Serializable {
private List<Attachment> attachments = new ArrayList<Attachment>();
private String content;
private int id;
private boolean isNew;
private Account owner;
private String ownerAddress;
private Set<Contact> receivers = new HashSet<Contact>();
private String sender;
private String title;
/**
* Hibernate purposes
*/
public Mail() { // $codepro.audit.disable
}
/**
* Unwraps light DTO object to heavy Hibernate object.
* @param dto Corresponding DTO class.
*/
public Mail(final MailDTO dto) {
for (final AttachmentDTO attachmentDTO : dto.getAttachments()) {
attachments.add(new Attachment(attachmentDTO));
}
content = dto.getContent();
id = dto.getId();
isNew = dto.isNew();
owner = dto.getOwner();
ownerAddress = dto.getOwnerAddress();
receivers = dto.getReceivers();
sender = dto.getSender();
title = dto.getTitle();
}
/**
* Inserts new attachment
* @param attachment
*/
public void addAttachment(final Attachment attachment) {
attachments.add(attachment);
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Mail)) {
return false;
}
final Mail other = (Mail) obj;
if (attachments == null) {
if (other.attachments != null) {
return false;
}
} else if (!attachments.equals(other.attachments)) {
return false;
}
if (content == null) {
if (other.content != null) {
return false;
}
} else if (!content.equals(other.content)) {
return false;
}
if (id != other.id) {
return false;
}
if (isNew != other.isNew) {
return false;
}
if (owner == null) {
if (other.owner != null) {
return false;
}
} else if (!owner.equals(other.owner)) {
return false;
}
if (ownerAddress == null) {
if (other.ownerAddress != null) {
return false;
}
} else if (!ownerAddress.equals(other.ownerAddress)) {
return false;
}
if (receivers == null) {
if (other.receivers != null) {
return false;
}
} else if (!receivers.equals(other.receivers)) {
return false;
}
if (sender == null) {
if (other.sender != null) {
return false;
}
} else if (!sender.equals(other.sender)) {
return false;
}
if (title == null) {
if (other.title != null) {
return false;
}
} else if (!title.equals(other.title)) {
return false;
}
return true;
}
/**
* @return the attachments
*/
public List<Attachment> getAttachments() {
return attachments;
}
/**
* @return the content
*/
public String getContent() {
return content;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @return the owner
*/
public Account getOwner() {
return owner;
}
/**
* @return the ownerAddress
*/
public String getOwnerAddress() {
return ownerAddress;
}
/**
* @return the receivers
*/
public Set<Contact> getReceivers() {
return receivers;
}
/**
* @return the sender
*/
public String getSender() {
return sender;
}
/**
* @return the title
*/
public String getTitle() {
return title;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((attachments == null) ? 0 : attachments.hashCode());
result = prime * result + ((content == null) ? 0 : content.hashCode());
result = prime * result + id;
result = prime * result + (isNew ? 1231 : 1237);
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
result = prime * result
+ ((ownerAddress == null) ? 0 : ownerAddress.hashCode());
result = prime * result
+ ((receivers == null) ? 0 : receivers.hashCode());
result = prime * result + ((sender == null) ? 0 : sender.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
/**
* @return the isNew
*/
public boolean isNew() {
return isNew;
}
/**
* @param attachments the attachments to set
*/
public void setAttachments(final List<Attachment> attachments) {
this.attachments = attachments;
}
/**
* @param content the content to set
*/
public void setContent(final String content) {
this.content = content;
}
/**
* @param id the id to set
*/
public void setId(final int id) {
this.id = id;
}
/**
* @param isNew the isNew to set
*/
public void setNew(final boolean isNew) {
this.isNew = isNew;
}
/**
* @param owner the owner to set
*/
public void setOwner(final Account owner) {
this.owner = owner;
}
/**
* @param ownerAddress the ownerAddress to set
*/
public void setOwnerAddress(final String ownerAddress) {
this.ownerAddress = ownerAddress;
}
/**
* @param receivers the receivers to set
*/
public void setReceivers(final Set<Contact> receivers) {
this.receivers = receivers;
}
/**
* @param sender the sender to set
*/
public void setSender(final String sender) {
this.sender = sender;
}
/**
* @param title the title to set
*/
public void setTitle(final String title) {
this.title = title;
}
}
附件:
// $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString
/**
*
*/
package com.xorty.mailclient.server.domain;
import java.io.Serializable;
import java.sql.SQLException;
import javax.sql.rowset.serial.SerialBlob;
import javax.sql.rowset.serial.SerialException;
import com.xorty.mailclient.client.domain.AttachmentDTO;
/**
* Heavy weight Hibernate Attachment
* @author MisoV
* @version 0.1
*/
public class Attachment implements Serializable {
private static final long serialVersionUID = 2047475939737947104L;
private SerialBlob blob;
private byte[] content;
private String contentid;
private String contenttype;
private String filename;
private int id;
private int mailId;
/**
* Hibernate purposes
*/
public Attachment() { // $codepro.audit.disable emptyMethod
}
/**
* Unwraps DTO to heavy weight hibernate object.
* @param dto
*/
public Attachment(final AttachmentDTO dto) {
content = dto.getContent();
contentid = dto.getContentid();
contenttype = dto.getContenttype();
filename = dto.getFilename();
id = dto.getId();
mailId = dto.getMailId();
try {
blob = new SerialBlob(content);
} catch (final SerialException e) {
e.printStackTrace();
} catch (final SQLException e) {
e.printStackTrace();
}
}
/**
* @return the blob
*/
public SerialBlob getBlob() {
return blob;
}
/**
* @return the content
*/
public byte[] getContent() {
return content;
}
/**
* @return the contentid
*/
public String getContentid() {
return contentid;
}
/**
* @return the contenttype
*/
public String getContenttype() {
return contenttype;
}
/**
* @return the filename
*/
public String getFilename() {
return filename;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @return the mailId
*/
public int getMailId() {
return mailId;
}
/**
* @param blob the blob to set
*/
public void setBlob(final SerialBlob blob) {
this.blob = blob;
}
/**
* @param content the content to set
*/
public void setContent(final byte[] content) {
this.content = content;
}
/**
* @param contentid the contentid to set
*/
public void setContentid(final String contentid) {
this.contentid = contentid;
}
/**
* @param contenttype the contenttype to set
*/
public void setContenttype(final String contenttype) {
this.contenttype = contenttype;
}
/**
* @param filename the filename to set
*/
public void setFilename(final String filename) {
this.filename = filename;
}
/**
* @param id the id to set
*/
public void setId(final int id) {
this.id = id;
}
/**
* @param mailId the mailId to set
*/
public void setMailId(final int mailId) {
this.mailId = mailId;
}
}
EDIT2:
Hibernate实际执行insert:
insert into Attachment (name, file, mail_idmail, idAttachment) values (?, ?, ?, ?)
正确设置值。它在session.save和session.get上都没有失败(它甚至可以获得正确的副本)。它在提交交易时失败。
我唯一可以得到的是:Cannot add or update a child row: a foreign key constraint fails (
maildb .
附件, CONSTRAINT
fk_Attachment_mail1 FOREIGN KEY (
mail_idmail ) REFERENCES
mail (
idmail {{ 1}}
答案 0 :(得分:2)
您收到约束违规例外。我认为这是从附件到邮件的外键,如
所示foreign key constraint fails (`maildb`.`attachment`, CONSTRAINT `fk_Attachment_mail1` FOREIGN KEY (`mail_idmail`)
我注意到你没有为你的id指定一个生成器。请参阅此文档
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id
由于您没有指定生成器,因此默认为“已分配”,这意味着您必须以编程方式将ID分配给之前保存它们的对象,这可能是也可能不是您想要的。
您没有向我们展示您的邮件实体与附件实体的关系,或者您如何创建实体的代码,这将帮助我更多...取决于您的操作方式,hibernate可能或可能无法在附件类中分配外键。
编辑 - 从你的评论中,你遗漏了一些东西。尝试在邮件的addAttachment方法中将邮件实体的ID分配给附件。如果您希望db分配id,您需要查找如何让表的id列自动增加您正在使用的任何RDBMS系统,然后更改添加生成器到实体的id映射。根据RDBMS,生成器可能是“标识”或“增量”。
答案 1 :(得分:0)
如果您想建立双向关系,您应该向您的附件指明Mail对象,而不仅仅是Id:
在Attcahment类中,删除
private int mailId; 并替换它 私人邮件;
使用正确的setter和getter。
在Xml映射文件中:
<property name="mailId"> <column name="mail_idmail"></column> </property>
应替换为:
<many-to-one name="mail" column="mail_idmail" not-null="true"/>
顺便说一下,你的hashCode / equals方法是垃圾。 你应该读这个:http://community.jboss.org/wiki/EqualsandHashCode 无论如何,最好不要覆盖它们而不是错误。