Total Pageviews

2015/04/30

2015/04 Travel

九份


無耳茶壺山


不厭亭


黃金瀑布


陰陽海


大肚美人山



2015/04/29

How to sort list of Java object with multiple fields

Problem
Assume I have a Java bean which named Fms432fa
 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
@Data
public class Fms432fa implements Serializable {
    // default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    private BigDecimal befalc1;
    private String accyr;
    private String dataType;
    private String rptNo;
    private BigDecimal alc1;
    private BigDecimal alc2;
    private BigDecimal alc3;
    private BigDecimal alc4;
    private BigDecimal alc5;
    private BigDecimal alc6;
    private BigDecimal alc7;
    private BigDecimal alc8;
    private BigDecimal alc9;
    private BigDecimal alc10;
    private BigDecimal alc11;
    private BigDecimal alc12;
    private String userid;
    private String updDateTime;

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

}

If I have a List of Fms432fa, and I would like to sort it by accyr, dataType and rptNo. How to do it?

Solution
Utilize Google Guava to fulfill this sorting requirement
1
2
3
4
5
6
7
8
        Collections.sort(fms432fas, new Comparator<Fms432fa>() {
            @Override
            public int compare(Fms432fa o1, Fms432fa o2) {
                return ComparisonChain.start().compare(o1.getAccyr(), o2.getAccyr())
                        .compare(o1.getDataType(), o2.getDataType())
                        .compare(o1.getRptNo(), o2.getRptNo()).result();
            }
        });


Reference
[1] http://blog.projectnibble.org/2013/06/21/ways-to-sort-lists-of-objects-in-java-based-on-multiple-fields/ 

2015/04/24

org.springframework.orm.jpa.JpaSystemException: null id generated for:class {0}

Problem
Here is my table schema with composite key

Owning to this table has composite key, so it will have primary key class and entity class.

 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