Tôi có một thực thể User
, một thực thể UserToApplication
và một thực thể Application
.Đặc điểm JPA dữ liệu mùa xuân sử dụng CriteriaBuilder w/mối quan hệ một đến nhiều
Một đơn User
có thể có quyền truy cập vào nhiều hơn Application
. Và một đơn Application
có thể được sử dụng bởi nhiều hơn một User
.
Đây là thực thể User
.
@Entity
@Table(name = "USER", schema = "UDB")
public class User {
private Long userId;
private Collection<Application> applications;
private String firstNm;
private String lastNm;
private String email;
@SequenceGenerator(name = "generator", sequenceName = "UDB.USER_SEQ", initialValue = 1, allocationSize = 1)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
@Column(name = "USER_ID", unique = true, nullable = false)
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
public Collection<Application> getApplications() {
return applications;
}
public void setApplications(Collection<Application> applications) {
this.applications = applications;
}
/* Other getters and setters omitted for brevity */
}
Đây là thực thể UserToApplication
.
@Entity
@Table(name = "USER_TO_APPLICATION", schema = "UDB")
public class Application {
private Long userToApplicationId;
private User user;
private Application application;
@SequenceGenerator(name = "generator", sequenceName = "UDB.USER_TO_APP_SEQ", initialValue = 0, allocationSize = 1)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
@Column(name = "USER_TO_APPLICATION_ID", unique = true, nullable = false)
public Long getUserToApplicationId() {
return userToApplicationId;
}
public void setUserToApplicationId(Long userToApplicationId) {
this.userToApplicationId = userToApplicationId;
}
@ManyToOne
@JoinColumn(name = "USER_ID", referencedColumnName = "USER_ID", nullable = false)
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@ManyToOne
@JoinColumn(name = "APPLICATION_ID", nullable = false)
public Application getApplication() {
return application;
}
}
Và đây là thực thể Application
.
@Entity
@Table(name = "APPLICATION", schema = "UDB")
public class Application {
private Long applicationId;
private String name;
private String code;
/* Getters and setters omitted for brevity */
}
Tôi có sau Specification
mà tôi sử dụng để tìm kiếm một User
bởi firstNm
, lastNm
, và email
.
public class UserSpecification {
public static Specification<User> findByFirstNmLastNmEmail(String firstNm, String lastNm, String email) {
return new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
final Predicate firstNmPredicate = null;
final Predicate lastNmPredicate = null;
final Predicate emailPredicate = null;
if (!StringUtils.isEmpty(firstNm)) {
firstNmPredicate = cb.like(cb.lower(root.get(User_.firstNm), firstNm));
}
if (!StringUtils.isEmpty(lastNm)) {
lastNmPredicate = cb.like(cb.lower(root.get(User_.lastNm), lastNm));
}
if (!StringUtils.isEmpty(email)) {
emailPredicate = cb.like(cb.lower(root.get(User_.email), email));
}
return cb.and(firstNmPredicate, lastNmPredicate, emailPredicate);
}
};
}
}
Và đây là User_
metamodel mà tôi có cho đến nay.
@StaticMetamodel(User.class)
public class User_ {
public static volatile SingularAttribute<User, String> firstNm;
public static volatile SingularAttribute<User, String> lastNm;
public static volatile SingularAttribute<User, String> email;
}
Bây giờ, tôi muốn cũng phải vượt qua trong một danh sách các id ứng dụng cho Specification
, chẳng hạn chữ ký phương pháp của nó sẽ là:
public static Specification<User> findByFirstNmLastNmEmailApp(String firstNm, String lastNm, String email, Collection<Long> appIds)
Vì vậy, câu hỏi của tôi là, tôi có thể thêm @OneToMany
ánh xạ tới số User_
metamodel cho trường Collection<Application> applications
của thực thể User
của tôi và sau đó làm cách nào để tham chiếu nó trong Specification
?
My hiện Specification
sẽ tương tự với truy vấn SQL sau:
select * from user u
where lower(first_nm) like '%firstNm%'
and lower(last_nm) like '%lastNm%'
and lower(email) like '%email%';
Và những gì tôi muốn đạt được trong mới Specification
sẽ là một cái gì đó như thế này:
select * from user u
join user_to_application uta on uta.user_id = u.user_id
where lower(u.first_nm) like '%firstNm%'
and lower(u.last_nm) like '%lastNm%'
and lower(u.email) like '%email%'
and uta.application_id in (appIds);
Có thể để làm loại ánh xạ này trong metamodel, và làm thế nào tôi có thể đạt được kết quả này trong số Specification
của tôi?
Tuyên bố biến trong lớp Application_ phải như sau, công khai tĩnh biến động SingularAttribute applicationId; thay vì công khai tĩnh SingularAttribute applicationId; Câu trả lời tổng thể là hoàn hảo mặc dù –
Avi
@Avi cảm ơn vì đã chỉ ra điều đó! Tôi đã sửa nó trong câu trả lời của tôi. –