@NamedNativeQuery与@SqlResultSetMapping为非实体

Mic*_*izo 8 java jpa named-query sqlresultsetmapping spring-data-jpa

我一直在用这篇文章作为例子.我有一个复杂的连接查询(这里简化).它从两个表(以及使用CASE的派生列)返回值的子集.我认为我不需要使用实体注释,因为从我的结果集返回的对象不是我的架构中的实际表.

我想要保存的非实体对象来自我的连接查询:

@SqlResultSetMapping(
           name="myMapping",
           classes={
              @ConstructorResult(
                   targetClass=CarLimitDelta.class,
                     columns={
                        @ColumnResult(name="caseCol"),
                        @ColumnResult(name="colA"),
                        @ColumnResult(name="colB"),
                        }
              )
           }
)
@NamedNativeQuery(name="CarLimitDelta.getCarLimitDelta", 
        resultSetMapping="myMapping", 
        query="SELECT CASE "+ 
           "WHEN t.foo IS NULL THEN 'INS' "+
           "WHEN s.foo IS NULL THEN 'DEL' "+
           "ELSE 'UPD' "+
        "END caseCol "+
     ", T.bar colA "+
     ", S.bar ColB "+
     "FROM tableA S "+
     "FULL JOIN TableB ON S.bar= T.bar")

public class CarLimitDelta {
        private String caseCol;
        private String colA;
        private String colB;


    //getters/setters/etc
    }
Run Code Online (Sandbox Code Playgroud)

我的回购:

@Repository
public interface CarLimitRepository extends CrudRepository<CarLimitDelta, String> {
    List<CarLimitDelta> getCarLimitDelta();
}
Run Code Online (Sandbox Code Playgroud)

我的服务:

@Service
public class CarLimitService {

    @Autowired
    CarLimitRepository carLimitRepository ;

    public void deleteAll() {
        carLimitRepository.deleteAll();
    }

    public List<CarLimitDelta> getCarLimitDelta() {
        return carLimitRepository.getCarLimitDelta();
    }


}
Run Code Online (Sandbox Code Playgroud)

我不知道如何让我的repo看到我的NamedNativeQuery中定义的新CarLimitDelta.getCarLimitDelta本机查询方法.我收到以下错误:

无效的派生查询!找不到类型CarLimitDelta的属性getCarLimitDelta!

cod*_*key 11

@SqlResultSetMapping@NamedNativeQuery注释必须上的@Entity,而不是在非实体POJO.

如果是实体Foo,则按如下方式添加注释:

@SqlResultSetMapping(
           name="myMapping",
           classes={
              @ConstructorResult(
                   targetClass=CarLimitDelta.class,
                     columns={
                        @ColumnResult(name="caseCol"),
                        @ColumnResult(name="colA"),
                        @ColumnResult(name="colB"),
                        }
              )
           }
)
@NamedNativeQuery(name="Foo.getCarLimitDelta", 
        resultSetMapping="myMapping", 
        query="...")
@Entity
public class Foo {
  ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,@NamedNativeQuery名称以实体名称为前缀,例如Foo.getCarLimitDelta.

然后将该方法添加到Foo存储库:

@Repository
public interface FooRepository extends CrudRepository<Foo, String> {
    List<CarLimitDelta> getCarLimitDelta();
}
Run Code Online (Sandbox Code Playgroud)

请注意,方法名称getCarLimitDelta匹配@NamedNativeQuery名称减去前缀.

  • 这有点愚蠢:您想要创建一个将数据放入 DTO(而不是实体)中的查询,并且您可以结合实体类来定义它。为了清楚地表达这一点,我通常在“虚拟类”上定义 SqlResultSetMapping: ```class DummyEntity() { @Id var id: Long? = null }``` (Kotlin),尤其是当我使用 JOOQ 生成本机 SQL 时。 (2认同)