Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用JPA标准API筛选版本字段上的实体_Jpa_Greatest N Per Group_Criteria Api_Self Join_Specification Pattern - Fatal编程技术网

使用JPA标准API筛选版本字段上的实体

使用JPA标准API筛选版本字段上的实体,jpa,greatest-n-per-group,criteria-api,self-join,specification-pattern,Jpa,Greatest N Per Group,Criteria Api,Self Join,Specification Pattern,我有一个具有嵌入id的实体,其中包含id和版本字段 @Entity @Table(name = "MyEntity") public class MyEntity { @EmbeddedId private MyEntityEmbeddedId compositeId; @Column private DateTime begin; @Column private DateTime end; } @Embeddable public cla

我有一个具有嵌入id的实体,其中包含id和版本字段

@Entity
@Table(name = "MyEntity")
public class MyEntity {
    @EmbeddedId
    private MyEntityEmbeddedId compositeId;

    @Column
    private DateTime begin;

    @Column
    private DateTime end;

}

@Embeddable
public class MyEntityEmbeddedId {
    @Column(name = "ID", nullable = false, updatable = false)
    private Long id;

    @Column(name = "VERSION", nullable = false, updatable = false)
    private Long version;

    public MyEntityEmbeddedId () {}

}
我需要用一些条件作为实体的过滤器来查询数据库。例如,我将请求一个日期和一个id列表

List<MyEntity> listEntities = getMyEntities(List<Long> ids, DateTime date);
如果以前的所有数据库记录都对应于筛选参数,我只需要获取这些记录,因为它们是对应id的版本号最高的记录:

+------+-----------+--------------------+
| id   | version   | began    |   end   |
+------+-----------+--------------------+ 
| 1    | 3         | ...      |   ...   |
| 2    | 2         | ...      |   ...   |
+------+-----------+--------------------+
目前,我执行请求,但我在我的服务中的方法中过滤版本,但如果该版本已在数据库请求中过滤,则我更希望这样做。我不需要检索在筛选版本后将被丢弃的记录

我正在寻找一种使用JPA标准API进行自连接的方法

在下面的链接中,我想知道如何在JPA Criteria API中翻译建议的SQL,似乎接受的答案将解决我的问题

选择yt1*
从您的表yt1
左外联接表yt2
开启(yt1.id=yt2.id和yt1.rev
我的问题是当我试图创建联接时。您需要提供链接到联接中第二个实体的第一个实体的属性。由于我想进行自连接,所以实体中没有指向自身的属性

Join<MyEntity, MyEntity> selfJoin = root.join(MyEntity_.???);
Join selfJoin=root.Join(MyEntity);
如你所见,我使用的是MyEntity的静态元模型。有没有一种方法可以使用JPA标准API进行自连接

或者,也许有另一种方法来构建我的请求,而不是像另一个问题中建议的那样使用自左连接

我正在使用SpringDataJPA规范构建带有谓词的查询。然后使用findAll(规范)。我还有另外两个规范方法来为WithId()和withDate()生成谓词。这让我可以使用用户提供的“待定数量”参数创建查询

public static Specification<MyEntity> withIdAndDate(final List<Long> ids, 
        final DateTime date) {
    return new Specification<MyEntity>() {

        @Override
        public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, 
                CriteriaBuilder cb){
            Join<MyEntity, MyEntity> selfJoin = root.join();
            Predicate pIds = withIds(ids).toPredicate(root, query, cb);
            Predicate pDate = withDate(date).toPredicate(root, query, cb);

            return cb.and(pIds, pDate);
        }

    };
}
带有ID和日期的公共静态规范(最终列表ID,
最终日期(日期){
返回新规范(){
@凌驾
公共谓词toPredicate(根根、标准查询、,
标准生成器(cb){
Join selfJoin=root.Join();
谓词pIds=withIds(ids).toPredicate(根、查询、cb);
谓词pDate=withDate(date).toPredicate(root,query,cb);
返回cb.和(PID、pDate);
}
};
}

非常感谢您的帮助和建议

最后,我成功地找到了一种方法,使用JPA Criteria API将我的MyEntity过滤到最新版本,因此我将与您分享我的代码,希望它能帮助这里的人

public static Specification<MyEntity> withIdAndDate(final List<Long> ids, 
        final DateTime date) {
    return new Specification<MyEntity>() {

        @Override
        public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, 
                CriteriaBuilder cb){

            Subquery<Long> subqueryVersion = query.subquery(Long.class);
            Root<MyEntity> entity1 = subqueryVersion.from(MyEntity.class);

            Expression<Long> expMaxVersion = cb.greatest(entity1
                .get(MyEntity_.compositeId).get(MyEntityEmbeddedId_.version));
            Expression<Long> expIdRoot = root.get(MyEntity_.compositeId)
                .get(MyEntityEmbeddedId_.id);
            Expression<Long> expIdEntity1 = entity1 .get(MyEntity_.compositeId)
                .get(MyEntityEmbeddedId_.id);
            Expression<Long> expVersionRoot = root.get(MyEntity_.compositeId)
                .get(MyEntityEmbeddedId_.version);

            Predicate pId = cb.equal(expIdRoot, expIdEntity1);
            Predicate pIds = withIds(ids).toPredicate(entity1, query, cb);
            Predicate pDate = withDate(date).toPredicate(entity1, query, cb);

            subqueryVersion.select(expMaxVersion);
            subqueryVersion.where(pId, pIds, pDate);

            Predicate pQuery = cb.equal(expVersionRoot, subqueryVersion);

            return cb.and(pQuery);
        }

    };
}
带有ID和日期的公共静态规范(最终列表ID,
最终日期(日期){
返回新规范(){
@凌驾
公共谓词toPredicate(根根、标准查询、,
标准生成器(cb){
Subquery subqueryVersion=query.Subquery(Long.class);
根entity1=子QueryVersion.from(MyEntity.class);
表达式expMaxVersion=cb.magest(entity1
.get(MyEntityEmbeddedId.version));
表达式expIdRoot=root.get(MyEntity_U2;.compositeId)
.get(MyEntityEmbeddedId\uUid);
表达式expIdEntity1=entity1.get(MyEntity\uuu.compositeId)
.get(MyEntityEmbeddedId\uUid);
表达式expVersionRoot=root.get(MyEntity_uuzy.compositeId)
.get(MyEntityEmbeddedId.version);
谓词pId=cb.equal(expIdRoot,expIdEntity1);
谓词pIds=withIds(ids).toPredicate(entity1,query,cb);
谓词pDate=withDate(date).toPredicate(entity1,query,cb);
subqueryVersion.select(expMaxVersion);
子查询版本,其中(pId、pId、pDate);
谓词pQuery=cb.equal(expVersionRoot,subqueryVersion);
返回cb.和(查询);
}
};
}
在下面的链接中,接受的答案帮助我在JPQL中构建查询,之后,我成功地将其转换为JPA Criteria API。我删除了查询的最后一部分,即“且不存在”部分。

public static Specification<MyEntity> withIdAndDate(final List<Long> ids, 
        final DateTime date) {
    return new Specification<MyEntity>() {

        @Override
        public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, 
                CriteriaBuilder cb){
            Join<MyEntity, MyEntity> selfJoin = root.join();
            Predicate pIds = withIds(ids).toPredicate(root, query, cb);
            Predicate pDate = withDate(date).toPredicate(root, query, cb);

            return cb.and(pIds, pDate);
        }

    };
}
public static Specification<MyEntity> withIdAndDate(final List<Long> ids, 
        final DateTime date) {
    return new Specification<MyEntity>() {

        @Override
        public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, 
                CriteriaBuilder cb){

            Subquery<Long> subqueryVersion = query.subquery(Long.class);
            Root<MyEntity> entity1 = subqueryVersion.from(MyEntity.class);

            Expression<Long> expMaxVersion = cb.greatest(entity1
                .get(MyEntity_.compositeId).get(MyEntityEmbeddedId_.version));
            Expression<Long> expIdRoot = root.get(MyEntity_.compositeId)
                .get(MyEntityEmbeddedId_.id);
            Expression<Long> expIdEntity1 = entity1 .get(MyEntity_.compositeId)
                .get(MyEntityEmbeddedId_.id);
            Expression<Long> expVersionRoot = root.get(MyEntity_.compositeId)
                .get(MyEntityEmbeddedId_.version);

            Predicate pId = cb.equal(expIdRoot, expIdEntity1);
            Predicate pIds = withIds(ids).toPredicate(entity1, query, cb);
            Predicate pDate = withDate(date).toPredicate(entity1, query, cb);

            subqueryVersion.select(expMaxVersion);
            subqueryVersion.where(pId, pIds, pDate);

            Predicate pQuery = cb.equal(expVersionRoot, subqueryVersion);

            return cb.and(pQuery);
        }

    };
}