问题
I have two entities defined as:
@Entity
public class FileMaster implements java.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long fileId;
@NotNull
@Column(unique = true)
private String fileNumber = "";
private String subject = "";
@Temporal(TemporalType.DATE)
private Date date=null;
private String authPerson="";
private String authDesign="";
private String department="";
@OneToMany(mappedBy = "fileMaster", cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name="id")
private Set<FileDetail> fileDetail = new HashSet<FileDetail>();
and second entity:
@Entity
public class FileDetail implements java.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long pdfId;
//@NotNull
@Column(unique = true)
private String name;
//@NotNull
@ManyToOne
private FileMaster fileMaster;
the following code simply tries to persist the two master-detail tables.. First insert goes well and it commits the record:
Set<FileDetail> pdfFileNames = newUpload.getPdfFileNames();
EntityManager em = Persistence.createEntityManagerFactory("fms")
.createEntityManager();
em.getTransaction().begin();
FileMaster fileMaster = new FileMaster();
fileMaster.setFileNumber((String) editorForm.getField("fileNumber").getValue());
fileMaster.setSubject((String) editorForm.getField("subject").getValue());
fileMaster.setAuthDesign((String)
editorForm.getField("authDesign").getValue());
fileMaster.setAuthPerson((String) editorForm.getField("authPerson").getValue());
fileMaster.setDate((Date) editorForm.getField("date").getValue());
fileMaster.setFileDetail(pdfFileNames);
em.persist(fileMaster);
Iterator<FileDetail> iter = pdfFileNames.iterator();
while(iter.hasNext()) {
FileDetail fileDetail = iter.next();
fileDetail.setName(fileDetail.getName());
fileDetail.setFileMaster(fileMaster);
em.persist(fileDetail);
}
em.getTransaction().commit();
em.close();
When I try to insert the second record.... It gives me PSQLException. Since Iam new to JPA... BTW Iam using Eclipselink and PostgreSQL with JPA....Iam finding it hard to resolve this issue. Could anyone please help me over this issue... let me paste the traces as well...
May 27, 2012 10:08:02 AM com.vaadin.Application terminalError
SEVERE: Terminal error:
com.vaadin.event.ListenerMethod$MethodException
Cause: javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "filedetail_pkey"
Detail: Key (pdfid)=(306) already exists.
Error Code: 0
Call: INSERT INTO FILEDETAIL (PDFID, NAME, FILEMASTER_FILEID) VALUES (?, ?, ?)
bind => [306, Manning Java Persistence with Hibernate 2nd.pdf, 3]
Query: InsertObjectQuery(Manning Java Persistence with Hibernate 2nd.pdf)
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:532)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:164)
at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1219)
at com.vaadin.ui.Button.fireClick(Button.java:550)
at com.vaadin.ui.Button.changeVariables(Button.java:217)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.changeVariables(AbstractCommunicationManager.java:1451)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1399)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1318)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:763)
at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:296)
at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:501)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:598)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:486)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:233)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
at org.eclipse.jetty.server.Server.handle(Server.java:350)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:900)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:954)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:851)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:606)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)
at java.lang.Thread.run(Unknown Source)
Caused by: javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "filedetail_pkey"
Detail: Key (pdfid)=(306) already exists.
Error Code: 0
Call: INSERT INTO FILEDETAIL (PDFID, NAME, FILEMASTER_FILEID) VALUES (?, ?, ?)
bind => [306, Manning Java Persistence with Hibernate 2nd.pdf, 3]
Query: InsertObjectQuery(Manning Java Persistence with Hibernate 2nd.pdf)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(Entit yTransactionImpl.java:102)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransac tionImpl.java:63)
at com.complete.raspberry.webui.PersonEditor.save(PersonEditor.java:178)
at com.complete.raspberry.webui.PersonEditor.buttonClick(PersonEditor.java:120)
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 com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:512)
... 36 more
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
回答1:
You should use GenerationType.IDENTITY
to generate pdfid
using auto increment instead of GenerationType.AUTO
for FileDetail
entity.
@Entity
public class FileDetail implements java.io.Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long pdfId;
}
GenerationType.IDENTITY
Indicates that the persistence provider must assign primary keys for the entity using a database identity column.
回答2:
Try setting logging on finest to see what is occurring.
Where does pdfFileNames come from? Are this existing objects, with existing ids? If they are existing, you should either be find/merging them, or create new ones with null ids. Ensure they do not have existing ids when you call persist.
If using SEQUENCE also ensure your increment matches your allocation size (default is 50).
来源:https://stackoverflow.com/questions/10771903/jpa-generating-duplicate-keys