简体   繁体   中英

spring jpa pageable sort PropertyReferenceException

I have a spring boot project and I use spring JPA. I have this model Receipt which has a column TransactionDate which its database column name is transaction_date . I'm calling the findAll(Predicate predicate, Pageable pageable) to get the desired data page.

It works completely fine when I create my predicate using the BooleanBuilder in my ReceiptService and passes it with the PageRequest without a sort it works fine but the moment I add a sort to it, it will throw the below exception:

org.springframework.data.mapping.PropertyReferenceException: No property transaction found for type Receipt!

and this is how I created my PageRequest

org.springframework.data.domain.Pageable pageable = new PageRequest(
        0, 
        10,
        Direction.DESC,
        "transaction_date");

and this is what my pageable looks like when I look at it in the debug mode

Page request [number: 0, size 10, sort: transaction_date: DESC]

but then from the exception it seems that it's cutting it from the _

here is my repository function: (since the conditions are coming from a search box which might have some other fields null or have a value, I realized it's easy to do it using the predicate)

public Page<Receipt> findAll(Predicate predicate, org.springframework.data.domain.Pageable pageable);

here is the Receipt Entity

@Entity
public class Receipt extends Base {

@Column(name="email")
private String Email;

@Column(name="bsid")
private String Bsid;


@Column(name="snap_shot")
private String SnapShot;

@Column(name="transaction_date")
private Date TransactionDate;

@Column(name="reference_number")
private String ReferenceNumber;

@Column(name="total_amount")
private Double TotalAmount;

@Column(name="submitted_by_user")
private boolean SubmittedByUser;

@Column(name="approval_date")
private Date ApprovalDate;

@ManyToOne
@JoinColumn(name="user_id")
private User User;

@ManyToOne
@JoinColumn(name="store_id")
private Store Store;

@Column(name="pending")
private boolean Pending;

@Column(name="declined")
private boolean Declined;

@Column(name="approved")
private boolean Approved;

public String getEmail() {
    return Email;
}

public void setEmail(String email) {
    Email = email.trim();
}

public String getBsid() {
    return Bsid;
}

public void setBsid(String bsid) {
    Bsid = bsid.trim();
}

public String getSnapShot() {
    return SnapShot;
}

public void setSnapShot(String snapShot) {
    SnapShot = snapShot.trim();
}

public Store getStore() {
    return Store;
}

public void setStore(Store store) {
    Store = store;
}

public Date getTransactionDate() {
    return TransactionDate;
}

public void setTransactionDate(Date transactionDate) {
    TransactionDate = transactionDate;
}

public String getReferenceNumber() {
    return ReferenceNumber;
}

public void setReferenceNumber(String referenceNumber) {
    ReferenceNumber = referenceNumber.trim();
}

public Double getTotalAmount() {
    return TotalAmount;
}

public void setTotalAmount(Double totalAmount) {
    TotalAmount = totalAmount;
}

public boolean isSubmittedByUser() {
    return SubmittedByUser;
}

public void setSubmittedByUser(boolean submittedByUser) {
    SubmittedByUser = submittedByUser;
}

public User getUser() {
    return User;
}

public void setUser(User user) {
    User = user;
}

public boolean isPending() {
    return Pending;
}

public void setPending(boolean pending) {
    Pending = pending;
}

public boolean isDeclined() {
    return Declined;
}

public void setDeclined(boolean declined) {
    Declined = declined;
}

public boolean isApproved() {
    return Approved;
}

public void setApproved(boolean approved) {
    Approved = approved;
}

public Date getApprovalDate() {
    return ApprovalDate;
}

public void setApprovalDate(Date approvalDate) {
    ApprovalDate = approvalDate;
}
}

Well, JPA in general (besides when you force the native SQL commands), expects to receive the java property name, in this case TransactionDate , instead of the real database column name transaction_date .

So to fix your code, basically, you should just make a call like:

org.springframework.data.domain.Pageable pageable = new PageRequest(
    0, 
    10,
    Direction.DESC,
    "TransactionDate");

That's being said, the java naming convention says that properties and variables should be in a lower camel case, as you can check into oracle documentation page .

I'm not sure if JPA (and in this case, spring-data), expects you to follow the naming convention as well. So if just passing the name as I told you to do so, have not worked, you probably need to change your entity to be like:

@Entity
public class Receipt extends Base {

    @Column(name="email")
    private String email;

    @Column(name="bsid")
    private String bsid;


    @Column(name="snap_shot")
    private String snapShot;

    @Column(name="transaction_date")
    private Date transactionDate;

    @Column(name="reference_number")
    private String referenceNumber;

    @Column(name="total_amount")
    private Double totalAmount;

    @Column(name="submitted_by_user")
    private boolean submittedByUser;

    @Column(name="approval_date")
    private Date approvalDate;

    @ManyToOne
    @JoinColumn(name="user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name="store_id")
    private Store store;

    @Column(name="pending")
    private boolean pending;

    @Column(name="declined")
    private boolean declined;

    @Column(name="approved")
    private boolean approved;

    // getters, setters, equals, hashcode, tostring, ...
}

And then, your call should be like:

org.springframework.data.domain.Pageable pageable = new PageRequest(
    0, 
    10,
    Direction.DESC,
    "transactionDate");

Cheers, Nikolas

Uhmm if i understand right your problem, you want to sort all the data, and then page it, right?

You can make it with the method naming.

Page<Receipt> findAllByOrderByTransactionDateDesc(Pageable pageable); 

If this fail you can also use a query

@Query("SELECT r FROM Receipt r ORDER BY  r.transaction_date DESC")
Page<Receipt> findAllQuery(Pageable pageable);

Then on your service you pass the Pageable to call it.

Page page = myRepo.findAllByOrderByTransactionDateDesc(new PageRequest(page, size));

Page page = myRepo.findAllQuery(new PageRequest(page, size));

Not sure if this is the right way or not but it fixed my problem for now.

So I just changed the TransactionDate in my entity to transactionDate and then changed the same column in the querydsl auto generated Q model as well (I copy pasted those classes into my models package so I can easily control them) and now it just works fine if I pass sorting column as "transactionDate".

I wouldn't mark this as an answer for few days so maybe some one would come up with the correct way of fixing this but just for a sake of some one who might have had the same issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM