在jpa上的NPE findAll与规范/谓词

时间:2014-10-31 17:48:14

标签: java hibernate jpa predicate specifications

我有以下规范,应该检查一个Magazines的{​​{1}}是否在File下的Magazines列表中:

Subscription

在我的服务中,我这样做:

public static Specification<File> getContainingMagazines(final long subscriptionId){
    return new Specification<File>() {
        @Override
        public Predicate toPredicate(Root<File> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

        Subquery<Subscription> subscriptionSubquery = query.subquery(Subscription.class);
        Root<Subscription> subscriptionRoot = subscriptionSubquery.from(Subscription.class);
        ListJoin<Subscription, Magazine> subscriptionMagazineJoin = subscriptionRoot.join(Subscription_.magazines);

        Path<Long> subscriptionIdPath = subscriptionRoot.get(Subscription_.id);

        subscriptionSubquery.
                select(subscriptionRoot).
                where(cb.equal(subscriptionIdPath, subscriptionId));

        ListJoin<File, Magazine> magazinesJoin = root.join(File_.magazines);

        return cb.and(magazinesJoin.get(Magazine_.id).in(subscriptionMagazineJoin.get(Magazine_.id)));
        }
    };
}

涉及的实体如下:

public int findFilesWithSubscription(long subscriptionId) {
        List<File> fileList = fileRepository.findAll(FileSpecs.getContainingMagazines(subscriptionId));
        return fileList.size();
    }

@Entity
@Table(name = "nim_file")
public class File

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
        name = "nim_file_magazines",
        joinColumns = @JoinColumn(name = "file_id"),
        inverseJoinColumns = @JoinColumn(name = "magazine_id")
)
private List<Magazine> magazines;

最后

@Entity
@Table(name = "nim_subscription")
public class Subscription

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "nim_subscription_magazines",
        joinColumns = @JoinColumn(name = "subscription_id"),
        inverseJoinColumns = @JoinColumn(name = "magazine_id")
)
private List<Magazine> magazines;

最后一个是查询表。

现在我正在使用DWR进行测试,因为我无法找到更好的快速测试方法,到目前为止,即使hibernate有@Entity @Table(name = "nim_magazine") public class Magazine ,也没有显示堆栈跟踪和sql。我只收到这条消息:

setShowSql(true)

所以我的问题是这些:

  1. 我做错了什么?
  2. 如何比dwr更好地测试/调试规范和/或谓词,以便我可以获得堆栈跟踪等等?

  3. 修改


    在转移到Junit测试类后,我获得了以下堆栈跟踪:

    2300777 [http-bio-9090-exec-4] WARN  o.d.dwrp.BaseCallMarshaller - --Erroring: batchId[2] message[java.lang.NullPointerException] 
    

1 个答案:

答案 0 :(得分:0)

我总是发现使用Criteria API非常麻烦且it may generate horrible SQL statements even for trivial joins

请尝试使用此HQL查询:

select f
from File f
inner join f.magazines file_magazine
where exists (
    select s 
    from Subscription s
    inner join s.magazines subscr_magazine
    where s.id = :subscription_id and subscr_magazine.id = file_magazine.id
)

虽然您也可以检查any/some/member of,但这些表达式可能导致非常复杂的SQL查询。尝试建议的子选择,看看它是如何进行的。

我不确定这是否有效,但您也可以使用带有额外连接子句的

select f
from File f
inner join f.magazines file_magazine
where exists (
    select s 
    from Subscription s
    inner join s.magazines subscr_magazine with subscr_magazine.id = file_magazine.id
    where s.id = :subscription_id
)

要记录al SQL查询以及参数,可以在应用程序数据源前面set up a datasurce-proxy