java – JPA在工作单元克隆中遇到Null或零主键

前端之家收集整理的这篇文章主要介绍了java – JPA在工作单元克隆中遇到Null或零主键前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我了解JPA并且有任务创建数据库并为其插入一些值.我想知道如何找出最近插入的对象的ID是什么,所以我找到了一种方法,我需要使用EntityManager的flush方法.

不幸的是我得到了

Null or zero primary key encountered in unit of work clone

我使用上述方法时的异常.我认为问题在于我的数据库自动增量上设置了所有ID(我使用ORACLE 11G Express),因此在提交之前它具有空值并且它回滚事务.

我能做些什么来修复它?

这是DB(ID是自动增量[oracle中的序列和触发器]):

  1. public class Client {
  2. public static void main(String[] args) {
  3. EntityManagerFactory emf =
  4. Persistence.createEntityManagerFactory("JpaIntroductionPU");
  5. EntityManager em = emf.createEntityManager();
  6. EntityTransaction et = em.getTransaction();
  7.  
  8. et.begin();
  9.  
  10. Address ad1 = new Address();
  11. ad1.setStreet("Skaraktki");
  12. ad1.setCode("64-340");
  13.  
  14. em.persist(ad1);
  15. em.flush();
  16.  
  17. System.out.println(ad1.getAId());
  18. et.commit();
  19. }
  20. }

Address class

  1. @Entity
  2. @Table(name = "ADDRESS")
  3. @NamedQueries({
  4. @NamedQuery(name = "Address.findAll",query = "SELECT a FROM Address a"),@NamedQuery(name = "Address.findByAId",query = "SELECT a FROM Address a WHERE a.aId = :aId"),@NamedQuery(name = "Address.findByStreet",query = "SELECT a FROM Address a WHERE a.street = :street"),@NamedQuery(name = "Address.findByCode",query = "SELECT a FROM Address a WHERE a.code = :code")})
  5. public class Address implements Serializable {
  6. private static final long serialVersionUID = 1L;
  7. // @Max(value=?) @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
  8. @Id
  9. @Basic(optional = false)
  10. @Column(name = "A_ID")
  11. private BigDecimal aId;
  12.  
  13. @Basic(optional = false)
  14. @Column(name = "STREET")
  15. private String street;
  16.  
  17. @Basic(optional = false)
  18. @Column(name = "CODE")
  19. private String code;
  20.  
  21. @OneToOne(cascade = CascadeType.ALL,mappedBy = "aId")
  22. private Employee employee;
  23.  
  24. @OneToOne(cascade = CascadeType.ALL,mappedBy = "aId")
  25. private Department department;
  26.  
  27. public Address() {
  28. }
  29.  
  30. public Address(BigDecimal aId) {
  31. this.aId = aId;
  32. }
  33.  
  34. public Address(BigDecimal aId,String street,String code) {
  35. this.aId = aId;
  36. this.street = street;
  37. this.code = code;
  38. }
  39.  
  40. public BigDecimal getAId() {
  41. return aId;
  42. }
  43.  
  44. public void setAId(BigDecimal aId) {
  45. this.aId = aId;
  46. }
  47.  
  48. public String getStreet() {
  49. return street;
  50. }
  51.  
  52. public void setStreet(String street) {
  53. this.street = street;
  54. }
  55.  
  56. public String getCode() {
  57. return code;
  58. }
  59.  
  60. public void setCode(String code) {
  61. this.code = code;
  62. }
  63.  
  64. public Employee getEmployee() {
  65. return employee;
  66. }
  67.  
  68. public void setEmployee(Employee employee) {
  69. this.employee = employee;
  70. }
  71.  
  72. public Department getDepartment() {
  73. return department;
  74. }
  75.  
  76. public void setDepartment(Department department) {
  77. this.department = department;
  78. }
  79.  
  80. @Override
  81. public int hashCode() {
  82. int hash = 0;
  83. hash += (aId != null ? aId.hashCode() : 0);
  84. return hash;
  85. }
  86.  
  87. @Override
  88. public boolean equals(Object object) {
  89. // TODO: Warning - this method won't work in the case the id fields are not set
  90. if (!(object instanceof Address)) {
  91. return false;
  92. }
  93. Address other = (Address) object;
  94. if ((this.aId == null && other.aId != null) || (this.aId != null && !this.aId.equals(other.aId))) {
  95. return false;
  96. }
  97. return true;
  98. }
  99.  
  100. @Override
  101. public String toString() {
  102. return "jpaintroduction.Address[ aId=" + aId + " ]";
  103. }
  104.  
  105. }

解决方法

您需要使用 @GeneratedValue注释您的id字段,以便JPA知道DB将自动生成id:
  1. @Id
  2. @Basic(optional = false)
  3. @Column(name = "A_ID")
  4. @SequenceGenerator( name = "mySeq",sequenceName = "MY_SEQ",allocationSize = 1,initialValue = 1 )
  5. @GeneratedValue(strategy=GenerationType.IDENTITY,generator="mySeq")
  6. private BigDecimal aId;

使用oracle,您可以使用GenerationType.IDENTITY和@SequenceGenerator,在这种情况下,您不需要触发器来查询序列并填充ID,JPA将为您执行此操作.我不确定GenerationType.AUTO是否可以与oracle一起使用,但如果确实如此,你需要一个触发器来查询序列并填充id. GenerationType.TABLE是最便携的解决方案,因为您使用由JPA管理的独立表来存储序列,它适用于所有数据库.

检查上面链接中的文档.

猜你在找的Java相关文章