Unable to locate appropriate constructor error for nested list object in kotlin and JpaRepository

后端 未结 3 1717
刺人心
刺人心 2021-01-25 15:10

I\'m facing the following error when JPA attempts to map the result from a query to the result repository method DTO:

org.hibernate.hql.internal.ast.QuerySyntaxE         


        
相关标签:
3条回答
  • 2021-01-25 15:48

    Why does your JdbcUserRepository returns a User object for findUserByUsername and not a DbUser? The solution should be obvious:

    override fun findUserByUsername(username: String): DbUser?
    

    And you do the mapping afterwards manually.

    You should think that people know why they introduced multiple representations of the same object instead of using a single representation as long as possible...

    0 讨论(0)
  • 2021-01-25 15:56

    I had to do an adtional step of casting like so cast(ds.demoId as java.lang.String) check this out :

    @Query( value = "select new com.api.models.DsResultStatus("+
                "cast(ds.demoId as java.lang.String),cast(ds.comp as java.lang.String),cast(ds.dc as java.lang.String),cast(be.buildUrl as java.lang.String)" +
                ",cast(be.username as java.lang.String),cast(tr.title as java.lang.String),cast(tr.result as java.lang.String))  \n" +
                "from DsEntity ds \n" +
                "inner join BtEntity be  ON ds.id = be.demoAssGuardingEntity\n" +
                "inner join  TrEntity tr ON be.id = tr.buildEntity\n" +
                "where ds.demoId in (?1) " +
                "and tr.title in ('\"Amazon\"','\"Google\"','\"FB\"') and tr.result = '\"failed\"'")
    
    List<DemoAssGuardingBuildResultStatus> getAssIdsWithFaliures(@Param("demoIds") Set<String> demoIds);
    
    0 讨论(0)
  • 2021-01-25 15:57

    The problem is that database query is able to return plain result only. Persistence provider can convert it to entities with nested entities lists. As for dto you have to solve the problem yourself.

    So you can get plain result using User dto with constructor as below

    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));  
    }
    

    Then you need repository method like this

    @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);
    

    Handle result in service layer

    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);
    }
    

    You can use the same approach for Kotlin

    0 讨论(0)
提交回复
热议问题