Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA一对一插入如何正确使用eclipselink_Java_Jpa_Eclipselink - Fatal编程技术网

Java JPA一对一插入如何正确使用eclipselink

Java JPA一对一插入如何正确使用eclipselink,java,jpa,eclipselink,Java,Jpa,Eclipselink,我试图用JPA和EclipseLink做简单的一对一映射 我在PostgreSQL中有以下DB结构 CREATE TABLE public.employee ( id SERIAL, firstname VARCHAR(20), lastname VARCHAR(20), CONSTRAINT employee_pkey PRIMARY KEY(id) ); CREATE TABLE public.employee_info ( id INTEGER NOT NULL,

我试图用JPA和EclipseLink做简单的一对一映射

我在PostgreSQL中有以下DB结构

CREATE TABLE public.employee (
  id SERIAL,
  firstname VARCHAR(20),
  lastname VARCHAR(20),
  CONSTRAINT employee_pkey PRIMARY KEY(id)
);
CREATE TABLE public.employee_info (
  id INTEGER NOT NULL,
  info TEXT DEFAULT ''::text NOT NULL,
  CONSTRAINT employee_info_pkey PRIMARY KEY(id),
  CONSTRAINT employee_info_fk FOREIGN KEY (id)
);
我试图用以下代码来反映这一点:

雇员:

@Entity
@Table(name = "employee")
public class Employee implements Serializable {
  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private Integer id;
  @Basic(optional = false)
  @Column(name = "firstname")
  private String firstname;
  @Basic(optional = false)
  @Column(name = "lastname")
  private String lastname;
  @OneToOne(cascade = CascadeType.ALL, mappedBy = "employee")
  private EmployeeInfo employeeInfo;
...
}
和员工信息

@Entity
@Table(name = "employee_info")
public class EmployeeInfo implements Serializable {
  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)  
  @Column(name = "id")
  private Integer id;
  @Column(name = "info")
  private String info;
  @OneToOne
  @PrimaryKeyJoinColumn
  private Employee employee;
...
}
现在我尝试插入数据:

    em.getTransaction().begin();
    Employee emp = new Employee();
    emp.setFirstname("FirstName");
    emp.setLastname("LastName");
    EmployeeInfo ei = new EmployeeInfo();
    ei.setInfo("some info");
    emp.setEmployeeInfo(ei);
    em.persist(emp);
    em.getTransaction().commit();
    em.close();
    emf.close();
并获取错误,因为JPA生成INSERT查询时没有指定第二个表的id

[EL Info]: 2015-02-28 14:15:31.741--ServerSession(1440332016)--EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
[EL Info]: connection: 2015-02-28 14:15:31.902--ServerSession(1440332016)--file:/D:/PROJEKTY/JAVA/JPATest3/build/classes/_JPATest3PU login successful
[EL Warning]: 2015-02-28 14:15:31.963--UnitOfWork(2115597658)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint
  Detail: Failing row contains (null, some info).
Error Code: 0
Call: INSERT INTO employee_info (info) VALUES (?)
    bind => [1 parameter bound]
Query: InsertObjectQuery(jpatest3.EmployeeInfo[ id=null ])
Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint
  Detail: Failing row contains (null, some info).
Error Code: 0
Call: INSERT INTO employee_info (info) VALUES (?)
    bind => [1 parameter bound]
Query: InsertObjectQuery(jpatest3.EmployeeInfo[ id=null ])
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:157)
    at jpatest3.JPATest3.main(JPATest3.java:32)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint
  Detail: Failing row contains (null, some info).
Error Code: 0
Call: INSERT INTO employee_info (info) VALUES (?)
    bind => [1 parameter bound]
Query: InsertObjectQuery(jpatest3.EmployeeInfo[ id=null ])
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1611)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:898)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:962)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:631)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
    at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2002)
    at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:377)
    at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:165)
    at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:180)
    at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:489)
    at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
    at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
    at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
    at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
    at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
    at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
    at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1737)
    at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:226)
    at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:193)
    at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:138)
    at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4207)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
    ... 1 more
Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint
  Detail: Failing row contains (null, some info).
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2157)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1886)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:555)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:363)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:890)
    ... 33 more
Java Result: 1
有人能告诉我我做错了什么,以及如何修复代码或数据结构,使其与JPA/Eclipselink一起正常工作吗

多谢各位

编辑1: 下面的代码可以工作,但这是应该的方式吗

Employee emp = new Employee();
emp.setFirstname("FirstName");
emp.setLastname("LastName");

em.persist(emp);
em.flush();

EmployeeInfo ei = new EmployeeInfo(emp.getId(), "some info");
em.persist(ei);
编辑2: 一段时间后,我发现如何实现我想要的。 我问错了问题。这不是一对一的映射。 它就像@SecondaryTable注释一样简单。使用@SecondaryTables注释,一个实体可以分布在两个或多个表中,这就是我想要实现的

@Entity
@Table(name = "employee")
@SecondaryTable(name = "employee_info")

public class Employee implements Serializable {

  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;
  private String name;
  @Column(table = "employee_info")
  private String longName;


您映射了由EmployeeInfo管理的关系,这意味着您还必须在新创建的EmployeeInfo对象上设置employee,因为JPA不会为您这样做。现在,JPA尝试在没有父对象的情况下保存employeeinfo,您会得到null键,但这还不是全部

employinfo主键是员工的主键,因此不能在声明@GeneratedValuestrategy=GenerationType.IDENTITY时生成它,但它必须采用其父employee对象的主键

您需要在EmployeeInfo中的@OneToOne映射上使用@Id或@PrimaryKeyJoinColumn来通知JPA密钥应该从父级派生,这里有解释:

最后,如果将employee上的ID生成从Identity更改为Table,效果会更好。这样,JPA在插入之前就知道密钥,可以在两个对象上设置密钥,否则它必须先插入并检索主键集

例如:

EmployeeInfo {
  @Id
  @Column(name = "id")
...
  @OneToOne
  @Id
  @JoinColumn(name="id", referencedColumnName="id")
  private Employee employee;
}

Employee emp = new Employee();
emp.setFirstname("FirstName");
emp.setLastname("LastName");

EmployeeInfo ei = new EmployeeInfo("some info");
ei.setEmploy(emp);
emp.setEmployeeInfo(ei);

em.persist(emp);

谢谢你的回答。事实上,EmployeeInfo中的@GeneratedValuestrategy=GenerationType.IDENTITY是错误的。虽然我解决了这个问题,但仍然有错误。我想继续使用数据库生成的标识。这是否意味着我必须手动刷新员工,然后将其id传递给employeeInfo?对我来说,这打破了整个想法。我遗漏了什么吗?当我手动刷新employee时,我添加了工作正常的代码,但这是正确的方法吗?您阅读了链接吗?将@Id添加到OneToOne映射中,删除生成的值,设置employee on info和info on employee对象。将您已有的员工cascade.all保留在您的父级上。我用一些代码编辑了答案。谢谢你的解释和代码。与此同时,我意识到应该怎么做。所有的问题都源于我网站上的误解。我认为我应该在Employee类中映射EmployeeInfo并坚持emp,而不是ei。但事实恰恰相反。我正在阅读Apress Pro JPA 2手册,现在很多事情都得到了解释,也更加清楚了,这也要感谢您的帮助,我非常感谢您的帮助。我仍然很好奇如何构建一个模型,其中员工数据分布在3 db表中。我认为目前的模式行不通。你能告诉我在那种情况下该怎么办吗?我们将有employee、employeeInfo1、employeeInfo2,所有这些都具有共享主键。
Employee e = new Employee();

e.setName("name");
e.setLongName("long name");

em.getTransaction().begin();
em.persist(e);

em.getTransaction().commit();
emf.close();
EmployeeInfo {
  @Id
  @Column(name = "id")
...
  @OneToOne
  @Id
  @JoinColumn(name="id", referencedColumnName="id")
  private Employee employee;
}

Employee emp = new Employee();
emp.setFirstname("FirstName");
emp.setLastname("LastName");

EmployeeInfo ei = new EmployeeInfo("some info");
ei.setEmploy(emp);
emp.setEmployeeInfo(ei);

em.persist(emp);