Here is my table schema with composite key
primary key class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | package gov.nta.entity.dbm; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Temporal; import javax.persistence.TemporalType; /** * The primary key class for the DBM400FA database table. * */ @Embeddable public class Dbm400faPK implements Serializable { // default serial version id, required for serializable classes. private static final long serialVersionUID = 1L; @Column(name = "CONTRACT_YEAR", unique = true, nullable = false, length = 4) private String contractYear; @Column(name = "BANK_SEQ_NO", unique = true, nullable = false, precision = 10) private long bankSeqNo; @Temporal(TemporalType.DATE) @Column(name = "CONTRACT_DATE", unique = true, nullable = false) private java.util.Date contractDate; public Dbm400faPK() { } public String getContractYear() { return this.contractYear; } public void setContractYear(String contractYear) { this.contractYear = contractYear; } public long getBankSeqNo() { return this.bankSeqNo; } public void setBankSeqNo(long bankSeqNo) { this.bankSeqNo = bankSeqNo; } public java.util.Date getContractDate() { return this.contractDate; } public void setContractDate(java.util.Date contractDate) { this.contractDate = contractDate; } public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof Dbm400faPK)) { return false; } Dbm400faPK castOther = (Dbm400faPK) other; return this.contractYear.equals(castOther.contractYear) && (this.bankSeqNo == castOther.bankSeqNo) && this.contractDate.equals(castOther.contractDate); } public int hashCode() { final int prime = 31; int hash = 17; hash = hash * prime + this.contractYear.hashCode(); hash = hash * prime + ((int) (this.bankSeqNo ^ (this.bankSeqNo >>> 32))); hash = hash * prime + this.contractDate.hashCode(); return hash; } } |
entity class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | package gov.nta.entity.dbm; import java.io.Serializable; import javax.persistence.*; import java.math.BigDecimal; import java.util.Date; /** * The persistent class for the DBM400FA database table. * */ @Entity @Table(name="DBM400FA") @NamedQuery(name="Dbm400fa.findAll", query="SELECT d FROM Dbm400fa d") public class Dbm400fa implements Serializable { private static final long serialVersionUID = 1L; @EmbeddedId private Dbm400faPK id; @Column(name="BORROW_AMOUNT", precision=20, scale=4) private BigDecimal borrowAmount; @Column(name="CONTRACT_AMOUNT", precision=20, scale=4) private BigDecimal contractAmount; @Temporal(TemporalType.DATE) @Column(name="CREATE_DATE") private Date createDate; @Column(name="DAILY_LIMIT", precision=20, scale=4) private BigDecimal dailyLimit; @Column(name="REVIEW_ID", length=20) private String reviewId; @Column(name="REVIEW_STATUS", length=1) private String reviewStatus; @Column(name="SOURCE_ID", precision=10) private BigDecimal sourceId; @Column(name="TOTAL_LIMIT", precision=20, scale=4) private BigDecimal totalLimit; @Temporal(TemporalType.DATE) @Column(name="UPDATE_DATE") private Date updateDate; @Column(name="USER_ID", length=20) private String userId; public Dbm400fa() { } public Dbm400faPK getId() { return this.id; } public void setId(Dbm400faPK id) { this.id = id; } public BigDecimal getBorrowAmount() { return this.borrowAmount; } public void setBorrowAmount(BigDecimal borrowAmount) { this.borrowAmount = borrowAmount; } public BigDecimal getContractAmount() { return this.contractAmount; } public void setContractAmount(BigDecimal contractAmount) { this.contractAmount = contractAmount; } public Date getCreateDate() { return this.createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public BigDecimal getDailyLimit() { return this.dailyLimit; } public void setDailyLimit(BigDecimal dailyLimit) { this.dailyLimit = dailyLimit; } public String getReviewId() { return this.reviewId; } public void setReviewId(String reviewId) { this.reviewId = reviewId; } public String getReviewStatus() { return this.reviewStatus; } public void setReviewStatus(String reviewStatus) { this.reviewStatus = reviewStatus; } public BigDecimal getSourceId() { return this.sourceId; } public void setSourceId(BigDecimal sourceId) { this.sourceId = sourceId; } public BigDecimal getTotalLimit() { return this.totalLimit; } public void setTotalLimit(BigDecimal totalLimit) { this.totalLimit = totalLimit; } public Date getUpdateDate() { return this.updateDate; } public void setUpdateDate(Date updateDate) { this.updateDate = updateDate; } public String getUserId() { return this.userId; } public void setUserId(String userId) { this.userId = userId; } } |
But as I execute this query SQL statement by JPA:
1 2 3 4 5 | SELECT * FROM DBM400FA WHERE CONTRACT_YEAR = :contractYr AND BANK_SEQ_NO = :bankSeqNo AND to_char(contract_date,'yyyyMMdd') = :contractDate + '19110000' |
It will throw exception:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | org.springframework.orm.jpa.JpaSystemException: null id generated for:class gov.nta.entity.dbm.Dbm400fa; nested exception is org.hibernate.id.IdentifierGenerationException: null id generated for:class gov.nta.entity.dbm.Dbm400fa at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:244) ~[spring-orm-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:155) ~[spring-orm-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) ~[spring-orm-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) ~[spring-tx-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) ~[spring-tx-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) ~[spring-tx-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:105) ~[spring-data-jpa-1.5.2.RELEASE.jar:na] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.3.RELEASE.jar:4.0.3.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.0.3.RELEASE.jar:4.0.3.RELEASE] at com.sun.proxy.$Proxy112.saveAndFlush(Unknown Source) ~[$Proxy112.class:na] at gov.nta.dbm.service.DbmBankContractService.saveDbm400faFromDbm400f1(DbmBankContractService.java:312) ~[classes/:na] |
Solution
You should use @IdClass instead of @EmbeddedId
Id class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | package gov.nta.entity.dbm; import java.io.Serializable; /** * The primary key class for the DBM400FA database table. * */ public class Dbm400faPK implements Serializable { // default serial version id, required for serializable classes. private static final long serialVersionUID = 1L; private String contractYear; private long bankSeqNo; private java.util.Date contractDate; public Dbm400faPK() { } public String getContractYear() { return this.contractYear; } public void setContractYear(String contractYear) { this.contractYear = contractYear; } public long getBankSeqNo() { return this.bankSeqNo; } public void setBankSeqNo(long bankSeqNo) { this.bankSeqNo = bankSeqNo; } public java.util.Date getContractDate() { return this.contractDate; } public void setContractDate(java.util.Date contractDate) { this.contractDate = contractDate; } public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof Dbm400faPK)) { return false; } Dbm400faPK castOther = (Dbm400faPK) other; return this.contractYear.equals(castOther.contractYear) && (this.bankSeqNo == castOther.bankSeqNo) && this.contractDate.equals(castOther.contractDate); } public int hashCode() { final int prime = 31; int hash = 17; hash = hash * prime + this.contractYear.hashCode(); hash = hash * prime + ((int) (this.bankSeqNo ^ (this.bankSeqNo >>> 32))); hash = hash * prime + this.contractDate.hashCode(); return hash; } } |
entity class with Id class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | package gov.nta.entity.dbm; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.NamedQuery; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.apache.commons.lang.builder.ToStringBuilder; /** * The persistent class for the DBM400FA database table. * */ @Entity @Table(name = "DBM400FA") @IdClass(Dbm400faPK.class) @NamedQuery(name = "Dbm400fa.findAll", query = "SELECT d FROM Dbm400fa d") public class Dbm400fa implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "CONTRACT_YEAR", unique = true, nullable = false, length = 4) private String contractYear; @Id @Column(name = "BANK_SEQ_NO", unique = true, nullable = false, precision = 10) private long bankSeqNo; @Id @Temporal(TemporalType.DATE) @Column(name = "CONTRACT_DATE", unique = true, nullable = false) private java.util.Date contractDate; @Column(name = "BORROW_AMOUNT", precision = 20, scale = 4) private BigDecimal borrowAmount; @Column(name = "CONTRACT_AMOUNT", precision = 20, scale = 4) private BigDecimal contractAmount; @Temporal(TemporalType.DATE) @Column(name = "CREATE_DATE") private Date createDate; @Column(name = "DAILY_LIMIT", precision = 20, scale = 4) private BigDecimal dailyLimit; @Column(name = "REVIEW_ID", length = 20) private String reviewId; @Column(name = "REVIEW_STATUS", length = 1) private String reviewStatus; @Column(name = "SOURCE_ID", precision = 10) private BigDecimal sourceId; @Column(name = "TOTAL_LIMIT", precision = 20, scale = 4) private BigDecimal totalLimit; @Temporal(TemporalType.DATE) @Column(name = "UPDATE_DATE") private Date updateDate; @Column(name = "USER_ID", length = 20) private String userId; public Dbm400fa() { } public BigDecimal getBorrowAmount() { return this.borrowAmount; } public void setBorrowAmount(BigDecimal borrowAmount) { this.borrowAmount = borrowAmount; } public BigDecimal getContractAmount() { return this.contractAmount; } public void setContractAmount(BigDecimal contractAmount) { this.contractAmount = contractAmount; } public Date getCreateDate() { return this.createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public BigDecimal getDailyLimit() { return this.dailyLimit; } public void setDailyLimit(BigDecimal dailyLimit) { this.dailyLimit = dailyLimit; } public String getReviewId() { return this.reviewId; } public void setReviewId(String reviewId) { this.reviewId = reviewId; } public String getReviewStatus() { return this.reviewStatus; } public void setReviewStatus(String reviewStatus) { this.reviewStatus = reviewStatus; } public BigDecimal getSourceId() { return this.sourceId; } public void setSourceId(BigDecimal sourceId) { this.sourceId = sourceId; } public BigDecimal getTotalLimit() { return this.totalLimit; } public void setTotalLimit(BigDecimal totalLimit) { this.totalLimit = totalLimit; } public Date getUpdateDate() { return this.updateDate; } public void setUpdateDate(Date updateDate) { this.updateDate = updateDate; } public String getUserId() { return this.userId; } public void setUserId(String userId) { this.userId = userId; } public String getContractYear() { return contractYear; } public void setContractYear(String contractYear) { this.contractYear = contractYear; } public long getBankSeqNo() { return bankSeqNo; } public void setBankSeqNo(long bankSeqNo) { this.bankSeqNo = bankSeqNo; } public java.util.Date getContractDate() { return contractDate; } public void setContractDate(java.util.Date contractDate) { this.contractDate = contractDate; } public String toString() { return ToStringBuilder.reflectionToString(this); } } |
Reference
[1] http://www.objectdb.com/java/jpa/entity/id