1

I am currently using JPA development project, but encountered a problem, please enlighten

Example:

@Query("
    SELECT 
        new CustomerMaintain(c.content, u, c.createTime, c.updateTime) 
    FROM 
        CustomerMaintain c 
    JOIN 
        c.user u
    WHERE 
        c.delFlag = FALSE AND c.customer.id = :customerId
")

CustomerMaintain.class DTO:

@Entity
@Table(name = "t_customer_maintain")
@DynamicUpdate
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "delFlag"})
public class CustomerMaintain {

    public CustomerMaintain() {
    }

    public CustomerMaintain(String content, User user, Date createTime, Date updateTime) {
        this.content = content;
        this.user = user;
        this.createTime = createTime;
        this.updateTime = updateTime;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(columnDefinition = "VARCHAR(512) DEFAULT ''")
    private String content;

    @ManyToOne(optional=false)
    private User user;

    @ManyToOne(optional=false)
    private Customer customer;

    @Column(columnDefinition = "TINYINT(1) DEFAULT FALSE ",insertable = false,updatable = false)
    private Boolean delFlag;

    @Column(columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP",insertable = false,updatable = false)
    private Date createTime;

    @Column(columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP",insertable = false,updatable = false)
    private Date updateTime;

    // omission getter setter method

}

I think there is only one sql query:

SELECT 
    c.content, 
    u.id, 
    u.name, 
    u.head, 
    c.createTime, 
    c.updateTime
FROM 
    t_customerMaintain c 
INNER JOIN 
    t_user u ...

But hibernate query result is this:

select 
    customerma0_.content as col_0_0_, 
    user1_.id as col_1_0_, /* only user.id fields */
    customerma0_.createTime as col_2_0_,
    customerma0_.updateTime as col_3_0_
from 
    t_customer_maintain customerma0_
inner join 
    t_user user1_ 
...

select 
    user0_.id as id1_4_0_,  
    user0_.head as head4_4_0_,
    user0_.name as name5_4_0_ 
from 
    t_user user0_ 
where 
    user0_.id=? /* user1_.id as col_1_0_ */

Question:

Why the first SQL query only user.id, and not user.id, user.name, user.head?

The last SQL query is superfluous.

I try to write like this:

SELECT 
    new CustomerMaintain(c.content, new User(u.id, u.name, u.head), c.createTime, c.updateTime) 

But doing so throws something abnormally: new User(u.id, u.name, u.head)

Please help me, this problem has been bothering me for a long time.

guan
  • 11
  • 3

1 Answers1

0

Could you explain why you think you need the NEW operator? The type of c is already CustomerMaintain, so SELECT c is enough.

If you want to explicitly fetch the User, use JOIN FETCH instead of JOIN. This way, the extra query for User will not be executed. Alternatively, you could use Hibernate's @Fetch(FetchMode.JOIN) to force Hibernate to use a join query (instead of a separate select query) to load CustomerMaintain.user whenever needed.

If you need finer-grained control over which properties get populated in the query result, use a fetch graph or a load graph as a query hint. Don't use NEW with entity constructors as results returned from such queries will not become managed.

crizzis
  • 9,978
  • 2
  • 28
  • 47