如何通过自定义DTO从MySQL表列获取JSON字符串列表及构造器报错解决
问题根源及修复方案
1. 映射列名与SQL别名不匹配
你的@SqlResultSetMapping里@ColumnResult的name是friendList,但原生SQL里给friend_list起的别名是friends,Hibernate找不到对应的列映射,导致无法匹配构造器参数。
2. DTO冗余注解+构造器匹配问题
StudentDto是DTO而非实体类,不需要@Type和@Column注解;另外@ConstructorResult会调用DTO的构造器,要确保映射的列和构造器参数的名称、类型完全匹配。
3. 查询结果强转错误
query.getResultList()返回的是List<StudentDto>,直接强转成StudentDto会抛出类型转换异常,应该用getSingleResult()(确保只会返回一条数据)或者合理处理列表结果。
修复后的代码
修改Student.java的@SqlResultSetMapping
@SqlResultSetMapping(name = "StudentMapping", classes = { @ConstructorResult(targetClass = StudentDto.class, columns = { // 别名与SQL保持一致,类型指定为String,后续由Hibernate转换为List<String> @ColumnResult(name = "friends", type = String.class)})}) @Data @Table(name = "student") public class Student { // 原有代码不变 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @Column(name = "name", nullable = false, length = 100) private String name; @Type(type = "json") @Column(name = "friend_list", columnDefinition = "json") @Builder.Default private List<String> friendsName = new ArrayList<>(); }
修改StudentDto.java
去掉冗余注解,保留核心字段与构造器:
@Data @Builder @AllArgsConstructor @NoArgsConstructor public class StudentDto implements Serializable { List<String> friends; }
修改StudentsCustomRepository.java
修正结果获取方式,同时避免SQL注入风险:
public StudentDto fetchStudentFriends(Long id) { String rawQuery = "select friend_list as friends from student where id = ?"; Query query = entityManager.createNativeQuery(rawQuery, "StudentMapping"); // 绑定参数,杜绝SQL注入 query.setParameter(1, id); // 确保仅返回一条数据时使用getSingleResult() return (StudentDto) query.getSingleResult(); }
额外注意点
- 若使用Hibernate 5+,需确保已配置正确的JSON类型处理器(比如
com.vladmihalcea.hibernate.type.json.JsonStringType),否则无法将JSON字符串正确转为List<String>。 - 永远不要用
String.format拼接SQL参数,这会引入严重的SQL注入风险,使用setParameter绑定参数是标准做法。
内容的提问来源于stack exchange,提问作者pradeexsu
相关产品推荐
相关产品推荐

