web-dev-qa-db-ja.com

非エンティティに対して@SqlResultSetMappingを使用した@NamedNativeQuery

私はこの post を例として使用しています。複雑な結合クエリがあります(ここでは簡略化しています)。 2つのテーブル(および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
    }

私のリポジトリ:

@Repository
public interface CarLimitRepository extends CrudRepository<CarLimitDelta, String> {
    List<CarLimitDelta> getCarLimitDelta();
}

私のサービス:

@Service
public class CarLimitService {

    @Autowired
    CarLimitRepository carLimitRepository ;

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

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


}

NamedNativeQueryで定義された新しいCarLimitDelta.getCarLimitDeltaネイティブクエリメソッドを表示するためにリポジトリを取得する方法がわかりません。次のエラーが発生します。

無効な派生クエリ!タイプCarLimitDeltaのプロパティgetCarLimitDeltaが見つかりません!

10
Micho Rizo

@SqlResultSetMappingおよび@NamedNativeQueryアノテーションは、エンティティでないPOJOではなく、@Entityにある必要があります。

エンティティが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 {
  ...
}

@NamedNativeQueryの名前には、エンティティ名が前に付いていることに注意してください。 Foo.getCarLimitDelta

次に、メソッドをFooリポジトリに追加します。

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

メソッド名getCarLimitDeltaは、@NamedNativeQuery名からプレフィックスを除いたものと一致することに注意してください。

14
codemonkey