无法为 kotlin 和 JpaRepository 中的嵌套列表对象找到适当的构造函数错误

2023-11-29

当 JPA 尝试将查询结果映射到结果存储库方法 DTO 时,我遇到以下错误:

org.hibernate.hql.internal.ast.QuerySyntaxException: 
Unable to locate appropriate constructor on class [com.example.dto.User]. Expected arguments are: java.lang.String, java.lang.String, com.example.repository.DbRole

我在用着spring-boot-starter-data-jpa and org.jetbrains.kotlin.plugin.jpa我的 Kotlin 项目中的插件。我有一个像这样定义的存储库:

@Repository
internal interface JdbcUserRepository : UserRepository, JpaRepository<DbUser, String> {

    override fun findUserByUsername(username: String): User?
}

请注意,JpaRepository (DbUser) 使用的类型与 findUserByUsername 方法 (User) 返回的类型不同,并且在上面的错误中,JPA 正确找到了 User 类(...类 [com.example.dto.User]...)但角色没有。它期望目标 DTO 中有一个 DbRole,这是错误的。

DbUser 是一个 @Entity 注解的类,并引用另一个名为 DbRole 的 @Entity 注解的类。两者定义如下:

@Entity
@Table(name = "user")
internal data class DbUser(
    @Id @Column val username: String,
    @Column val password: String,
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
        name = "user_role",
        joinColumns = [JoinColumn(name = "username", referencedColumnName = "username")],
        inverseJoinColumns = [JoinColumn(name = "role_id", referencedColumnName = "id")]
    ) val roles: List<DbRole>
)

@Entity
@Table(name = "role")
internal data class DbRole(
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long,
    @Column val roleName: String,
    @Column val description: String
)

以下是 JPA 必须将结果映射到的类:

data class User(
    val username: String,
    val password: String,
    val roles: List<Role>
)

data class Role(val roleName: String, val description: String)

有谁知道如何解决这个问题并且JPA正确找到DbRole的嵌套实体列表并将其映射到Role的嵌套DTO列表?


问题是数据库查询只能返回普通结果。持久性提供程序可以将其转换为具有嵌套实体列表的实体。至于dto你必须自己解决问题。

所以你可以使用得到简单的结果Userdto 与构造函数如下

public User(String username, String password, String roleName, String roleDescription) {
     this.username = username;
     this.password = password;
     roles = new ArrayList<>();
     roles.add(new Role(roleName, roleDescription));  
}

那么你需要像这样的存储库方法

@Query("select new com.example.dto.User(u.username, u.password, r.roleName, r.description) from DbUser u join u.roles r where u.username=:username")
List<User> findUserByUsername(@Param("username") String username);

在服务层处理结果

public Optional<User> findUserByUsername(username) {
    List<User> users = findUserByUsername(username);

    if(users.isEmpty()) {
        return Optional.empty();
    }

    User user = users.get(0);
    if(users.size() > 1) {
         users.subList(1, users.size()).forEach(u -> user.getRoles().addAll(u.getRoles()));
    }

    return Optional.of(user);
}

您可以使用相同的方法Kotlin

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法为 kotlin 和 JpaRepository 中的嵌套列表对象找到适当的构造函数错误 的相关文章

随机推荐