Spring 数据 Jpa 和规范 - 如何处理 ManyToOne 和 ManyToMany 关系?
Spring Data Jpa and Specification - how to work with ManyToOne and ManyToMany relations?
我的项目中有一个简单的模型。
[UpdatePackage] >- (ManyToOne) - [版本] -< [用例] - (ManyToMany)
public class UpdatePackage implements Comparable<UpdatePackage> {
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = COLUMN_ORIG_VERSION, nullable = true)
private Version origVersion;
// setters and getters
}
@Entity
@Table(name = Version.TABLE_NAME)
public class Version {
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = JVUC_TABLE, joinColumns = { @JoinColumn(name = JVUC_COLUMN_VERSION, referencedColumnName = COLUMN_ID) }, inverseJoinColumns = { @JoinColumn(name = JVUC_COLUMN_USECASE, referencedColumnName = UseCase.COLUMN_ID) })
private final Set<UseCase> useCases = new HashSet<UseCase>();
// setters and getters
}
@Entity
@Table(name = UseCase.TABLE_NAME)
public class UseCase {
@Column(name = COLUMN_NAME, nullable = false)
private String name;
// setters and getters
}
为了实现过滤器,我想使用 Spring 来自 spring.data.jpa.domain
的数据 Jpa 和规范
例如,我想找到具有给定用例名称的 UpdatePackage 列表。
我知道对于 ManyToOne 关系,我需要使用 Join,对于 ManyToMany,我需要使用 Fetch。
我的规范接口实现如下所示:
public static Specification<UpdatePackage> useCaseNames(final List<String> useCaseNames) {
return new Specification<UpdatePackage>() {
@Override
public Predicate toPredicate(Root<UpdatePackage> root, CriteriaQuery<?> query,
CriteriaBuilder cb) {
final Join<UpdatePackage, Version> version = root.join(UpdatePackage_.destVersion,
JoinType.LEFT);
Fetch<Version, UseCase> useCase = version.fetch(Version_.useCases, JoinType.LEFT);
return null;
// return useCase.get(UseCase_.name).in(useCaseNames);
}
};
}
当我 运行 进行集成测试时,我在行中得到了 NPException:
Fetch<Version, UseCase> useCase = version.fetch(Version_.useCases, JoinType.LEFT);
因为对象版本的字段连接和提取为空。
我不知道我做错了什么,我在网上找不到任何答案。
有人知道这段代码有什么问题吗?
堆栈:
java.lang.NullPointerException
在 org.hibernate.ejb.criteria.path.AbstractFromImpl.constructJoin(AbstractFromImpl.java:261)
在 org.hibernate.ejb.criteria.path.AbstractFromImpl.fetch(AbstractFromImpl.java:549)
我找到了解决办法。我在静态模型中有一个错误。
静态模型
来自:
public static volatile SingularAttribute<Version, UseCase> useCases;
收件人:
public static volatile SetAttribute<Version, UseCase> useCases;
并在实施规范中:
public static Specification<UpdatePackage> useCaseNames(final List<String> useCaseNames) {
return new Specification<UpdatePackage>() {
@Override
public Predicate toPredicate(Root<UpdatePackage> root, CriteriaQuery<?> query,
CriteriaBuilder cb) {
final Join<UpdatePackage, Version> version = root.join(UpdatePackage_.destVersion,
JoinType.LEFT);
final Join<Version, UseCase> useCase = version.join(Version_.useCases);
return useCase.get(UseCase_.name).in(useCaseNames);
}
};
}
我的项目中有一个简单的模型。
[UpdatePackage] >- (ManyToOne) - [版本] -< [用例] - (ManyToMany)
public class UpdatePackage implements Comparable<UpdatePackage> {
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = COLUMN_ORIG_VERSION, nullable = true)
private Version origVersion;
// setters and getters
}
@Entity
@Table(name = Version.TABLE_NAME)
public class Version {
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = JVUC_TABLE, joinColumns = { @JoinColumn(name = JVUC_COLUMN_VERSION, referencedColumnName = COLUMN_ID) }, inverseJoinColumns = { @JoinColumn(name = JVUC_COLUMN_USECASE, referencedColumnName = UseCase.COLUMN_ID) })
private final Set<UseCase> useCases = new HashSet<UseCase>();
// setters and getters
}
@Entity
@Table(name = UseCase.TABLE_NAME)
public class UseCase {
@Column(name = COLUMN_NAME, nullable = false)
private String name;
// setters and getters
}
为了实现过滤器,我想使用 Spring 来自 spring.data.jpa.domain
的数据 Jpa 和规范例如,我想找到具有给定用例名称的 UpdatePackage 列表。
我知道对于 ManyToOne 关系,我需要使用 Join,对于 ManyToMany,我需要使用 Fetch。
我的规范接口实现如下所示:
public static Specification<UpdatePackage> useCaseNames(final List<String> useCaseNames) {
return new Specification<UpdatePackage>() {
@Override
public Predicate toPredicate(Root<UpdatePackage> root, CriteriaQuery<?> query,
CriteriaBuilder cb) {
final Join<UpdatePackage, Version> version = root.join(UpdatePackage_.destVersion,
JoinType.LEFT);
Fetch<Version, UseCase> useCase = version.fetch(Version_.useCases, JoinType.LEFT);
return null;
// return useCase.get(UseCase_.name).in(useCaseNames);
}
};
}
当我 运行 进行集成测试时,我在行中得到了 NPException:
Fetch<Version, UseCase> useCase = version.fetch(Version_.useCases, JoinType.LEFT);
因为对象版本的字段连接和提取为空。
我不知道我做错了什么,我在网上找不到任何答案。
有人知道这段代码有什么问题吗?
堆栈: java.lang.NullPointerException 在 org.hibernate.ejb.criteria.path.AbstractFromImpl.constructJoin(AbstractFromImpl.java:261) 在 org.hibernate.ejb.criteria.path.AbstractFromImpl.fetch(AbstractFromImpl.java:549)
我找到了解决办法。我在静态模型中有一个错误。
静态模型 来自:
public static volatile SingularAttribute<Version, UseCase> useCases;
收件人:
public static volatile SetAttribute<Version, UseCase> useCases;
并在实施规范中:
public static Specification<UpdatePackage> useCaseNames(final List<String> useCaseNames) {
return new Specification<UpdatePackage>() {
@Override
public Predicate toPredicate(Root<UpdatePackage> root, CriteriaQuery<?> query,
CriteriaBuilder cb) {
final Join<UpdatePackage, Version> version = root.join(UpdatePackage_.destVersion,
JoinType.LEFT);
final Join<Version, UseCase> useCase = version.join(Version_.useCases);
return useCase.get(UseCase_.name).in(useCaseNames);
}
};
}