在Hibernate 5中映射单向一对一关系
我的问题很简单,为什么hibernate在我持久化一个帐户实体时,不将帐户实体的主键自动带到用户实体,比如@mapsId 如果我们考虑到这个映射:在Hibernate 5中映射单向一对一关系,hibernate,jpa,Hibernate,Jpa,我的问题很简单,为什么hibernate在我持久化一个帐户实体时,不将帐户实体的主键自动带到用户实体,比如@mapsId 如果我们考虑到这个映射: @Entity @Table(name="account") @Getter @Setter public class Account implements Serializable{ /** * */ private static final long serialVersionUID = 1L;
@Entity
@Table(name="account")
@Getter
@Setter
public class Account implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.AUTO, generator="native")
@GenericGenerator(name = "native", strategy = "native")
private int accountId;
@Column(name="email")
private String email;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn(name="id", referencedColumnName="pk_account$user")
private User user;
}
@Entity
@Table(name="user")
@Getter
@Setter
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name="pk_account$user")
private int userId;
@Column(name="identification_number")
private String identificationNumber;
}
然后我做这个:
public static void main( String[] args )
{
SessionFactory sessionFactory;
Configuration configuration= new Configuration();
configuration.configure();
sessionFactory=configuration.buildSessionFactory();
Session session= sessionFactory.openSession();
session.beginTransaction();
Account account= new Account();
account.setEmail("new@gmail.com");
User user= new User();
user.setIdentificationNumber("11462727272");
account.setUser(user);
session.persist(account);
session.getTransaction().commit();
}
我有一个错误:
Hibernate: insert into account (email) values (?)
Hibernate: insert into user (identification_number, pk_account$user) values (?, ?)
Jun 04, 2018 5:41:16 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1452, SQLState: 23000
Jun 04, 2018 5:41:16 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Cannot add or update a child row: a foreign key constraint fails (`prueba`.`user`, CONSTRAINT `fk_user_account` FOREIGN KEY (`pk_account$user`) REFERENCES `account` (`id`))
Jun 04, 2018 5:41:16 PM org.hibernate.internal.ExceptionMapperStandardImpl mapManagedFlushFailure
ERROR: HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1460)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:511)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3278)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2474)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:98)
at com.espiritware.pruebaOneToOne.App.main(App.java:32)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:178)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3136)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3651)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:90)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1454)
... 9 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`prueba`.`user`, CONSTRAINT `fk_user_account` FOREIGN KEY (`pk_account$user`) REFERENCES `account` (`id`))
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:115)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:960)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1116)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1066)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1396)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1051)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)
... 17 more
我期望:
public static void main( String[] args )
{
SessionFactory sessionFactory;
Configuration configuration= new Configuration();
configuration.configure();
sessionFactory=configuration.buildSessionFactory();
Session session= sessionFactory.openSession();
session.beginTransaction();
Account account= new Account();
account.setEmail("new@gmail.com");
session.persist(account);
User user= new User();
user.setUserId(account.getAccountId());
user.setIdentificationNumber("11462727272");
account.setUser(user);
session.persist(account);
session.getTransaction().commit();
}
如果有人能给你一个解释,我将不胜感激。我希望在不进行手动分配的情况下执行此操作,保持单向关系JPA规范表明您不应再将
@PrimaryKeyJoinColumn
用于@OneToOne
映射。由于用户
主键由帐户
确定,您可以尝试双向一对一并使用“派生标识”:
第2.4.1节中讨论了派生身份(带有示例)。您能否在最后一句中添加指向JPA 2.2规范PDF的链接/url?
@Entity
@Table(name="account")
@Getter
@Setter
public class Account implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.AUTO, generator="native")
@GenericGenerator(name = "native", strategy = "native")
private int accountId;
@Column(name="email")
private String email;
@OneToOne(cascade = CascadeType.ALL, mappedBy="account")
private User user;
}
@Entity
@Table(name="user")
@Getter
@Setter
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="pk_account$user")
private int userId;
@OneToOne
@MapsId
private Account account;
@Column(name="identification_number")
private String identificationNumber;
}