Spring Boot接口投影仅返回null。

7

我正在使用Spring Data JPA。目标是从我的实体表中仅获取“标题”和“创建日期”两列数据。显然,这可以通过一些称为接口投影的东西实现。因此,我创建了该接口并将返回类型更改为该接口,接口得到返回,但当我调用get方法/返回结果时,值只为null。

这是我的实体类:

import java.time.Instant;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import com.sun.istack.NotNull;

@Entity
public class Entry {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    
    @Column(columnDefinition="timestamptz")
    Instant creationDate;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="userId")
    @NotNull
    private User user;
    
    @Column(columnDefinition = "varchar(256)") 
    String title;
    @Column(columnDefinition = "text") 
    String text;
    
    
    
    
    public Entry() {
        creationDate = Instant.now();
    }




    public long getId() {
        return id;
    }




    public void setId(long id) {
        this.id = id;
    }




    public Instant getCreationDate() {
        return creationDate;
    }




    public void setCreationDate(Instant creationDate) {
        this.creationDate = creationDate;
    }




    public User getUser() {
        return user;
    }




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




    public String getTitle() {
        return title;
    }




    public void setTitle(String title) {
        this.title = title;
    }




    public String getText() {
        return text;
    }




    public void setText(String text) {
        this.text = text;
    }
    
    
    
    

}

这是我的接口:

    import java.time.Instant;
    
    public interface EntryTitleDateAndUserIdDTO {
        public String getTitle();
        public Instant getCreationDate();
        //User getUser();
        

}

这是我的代码库:
public interface EntryRepository extends JpaRepository<Entry, Long>{
    
    @Query("SELECT e.title, e.creationDate FROM Entry e WHERE e.user = ?1")
    ArrayList<EntryTitleDateAndUserIdDTO> getAllEntriesOfUser(User user);
    
    @Query("SELECT e FROM Entry e WHERE e.id = ?1 AND e.user = ?2")
    Entry getEntryOfUser(Long entryId, Long userId );
    
    @Query("DELETE FROM Entry e WHERE e.id = ?1 AND e.user = ?2")
    Entry deleteEntry(Long entryId, Long userId );

}

这是我的控制器:

@RestController
@RequestMapping("/User")
public class UserController {
    
    @Autowired
    UserRepository userRepo;
    
    @Autowired
    EntryRepository entryRepo;
    
    
    
    @GetMapping("/{userId}/Entries")
    private ArrayList<EntryTitleDateAndUserIdDTO> getAllEntries(@PathVariable Long userId) {
        
        User u = userRepo.findById(userId).get();
        ArrayList<EntryTitleDateAndUserIdDTO> e = entryRepo.getAllEntriesOfUser(u);
        
        
        
        return e;
        
    }

这是在浏览器中的输出结果:

[{"title":null,"creationDate":null}]

这是在数据库中保存的内容: Postgresql入口表

这是由Spring生成的查询:

    select
        user0_.id as id1_1_0_,
        user0_.email as email2_1_0_,
        user0_.join_date as join_dat3_1_0_,
        user0_.password as password4_1_0_,
        user0_.username as username5_1_0_ 
    from
        public.user user0_ 
    where
        user0_.id=?
2021-11-04 18:13:35.417 TRACE 5104 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1]
2021-11-04 18:13:35.447 DEBUG 5104 --- [nio-8080-exec-1] org.hibernate.SQL                        : 
    select
        entry0_.title as col_0_0_,
        entry0_.creation_date as col_1_0_ 
    from
        public.entry entry0_ 
    where
        entry0_.user_id=?
2021-11-04 18:13:35.448 TRACE 5104 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1]

如果有人能帮忙,将不胜感激,先行致谢。

2个回答

27

尝试将您的选择字段别名与您的投影接口方法 getTitlegetCreationDate 完全匹配。

 @Query("SELECT e.title as title, e.creationDate as creationDate FROM Entry e WHERE e.user = ?1")

你真是个天才,非常感谢,这解决了问题! - Timon
是的,你很聪明!你也救了我的一天! - microwth
谢谢,creationDate 帮了我,我需要用 CamelCase 而不是 snake_case 别名它们。 - k4anubhav

1

由于您正在使用Spring Data JPA,您可以使用派生查询代替注释所有查询。这还可以消除别名的需要。

public interface EntryRepository extends JpaRepository<Entry, Long>{
    
    ArrayList<EntryTitleDateAndUserIdDTO> findByUser(User user);
    
    Entry findByIdAndUserId(Long id, Long userId );
    
    void deleteByIdAndUserId(Long id, Long userId );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接