在Spring Data JPA中查询Student表时关联获取Student_Type表数据
解决Spring Data JPA查询Student时关联获取Student_Type的type字段问题
一、先修正实体类中的错误
你的实体类存在拼写、类型匹配等问题,这是映射失败的核心原因,先逐一修正:
1. Student实体修正
@Entity // 修正拼写:@Enity -> @Entity @Table(schema="DATA", name="STUDENT") @Data @Builder @AllArgsConstructor @NoArgsConstructor public class Student { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @Column(name="fname") private String fname; // 修正:string -> String,fanme -> fname @Column(name="lname") private String lname; // 修正:string -> String,lanme -> lname // 方案一会用到:双向关联StudentType;若要保留原@Transient字段,可配合@PostLoad自动赋值 // @Transient // private String config_type; @OneToOne(mappedBy = "student", fetch = FetchType.EAGER) private StudentType studentType; }
2. StudentType实体修正
@Entity // 修正拼写:@Enity -> @Entity @Table(schema="DATA", name="STUDENT_TYPE") @Data @Builder @AllArgsConstructor @NoArgsConstructor public class StudentType { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @Column(name="type") private String type; // 修正:string -> String // 可选:若保留该字段,类型改为Long(匹配Student的id类型) // @Column(name="stud_id") // private Long studId; // 修正:string -> Long,stud_id -> studId(符合Java命名规范) @OneToOne(optional=false) @JoinColumn( // 修正拼写:@JoinCoulumn -> @JoinColumn name="stud_id", referencedColumnName= "id", insertable=false, updatable=false // 修正:updateble -> updatable ) private Student student; }
二、解决方案
方案一:通过JPA关联映射自动获取
修正实体关联后,直接查询Student即可自动加载对应StudentType,进而获取type字段:
- 在StudentRepository中添加基础查询方法:
public interface StudentRepository extends JpaRepository<Student, Long> { List<Student> findAll(); }
- 使用时获取type:
// 查询所有学生 List<Student> students = studentRepository.findAll(); // 遍历获取每个学生的类型 for(Student s : students) { String type = s.getStudentType() != null ? s.getStudentType().getType() : null; // 若保留@Transient的config_type,可在Student实体中添加@PostLoad自动赋值: // @PostLoad // private void postLoad() { // this.config_type = studentType != null ? studentType.getType() : null; // } }
方案二:通过JPQL/原生查询返回DTO(无需修改实体关联)
如果不想调整实体关联结构,可创建DTO接收查询结果,避免字段映射问题:
- 创建StudentDTO类:
@Data @AllArgsConstructor public class StudentDTO { private String fname; private String lname; private String configType; }
- 在StudentRepository中编写JPQL查询:
public interface StudentRepository extends JpaRepository<Student, Long> { @Query("SELECT new com.yourpackage.dto.StudentDTO(s.fname, s.lname, st.type) " + "FROM Student s LEFT JOIN StudentType st ON s.id = st.studId") List<StudentDTO> findAllWithType(); }
注意替换
com.yourpackage.dto为你的DTO实际包路径
- 或者使用原生查询(需匹配数据库表名和字段名):
@Query(value = "SELECT s.fname, s.lname, st.type AS config_type " + "FROM DATA.STUDENT s LEFT JOIN DATA.STUDENT_TYPE st ON s.id = st.stud_id", nativeQuery = true) List<Object[]> findAllWithTypeNative();
在服务层转换为Student或DTO:
List<Object[]> resultList = studentRepository.findAllWithTypeNative(); List<Student> students = new ArrayList<>(); for(Object[] row : resultList) { Student student = new Student(); student.setFname((String) row[0]); student.setLname((String) row[1]); student.setConfig_type((String) row[2]); students.add(student); }
三、原有原生查询的问题说明
你之前的原生查询无法直接返回List<Student>,原因是:
- 查询仅返回
fname、lname、config_type三个字段,而Student实体包含id等其他字段,JPA无法自动补全缺失值 @Transient标记的字段不参与JPA持久化映射,查询结果无法自动填充到该字段
内容的提问来源于stack exchange,提问作者Rijo
相关产品推荐
相关产品推荐

