条件继承:按子字段加入和搜索
Criteria inheritance: join and search by child field
我有根实体:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "applications")
public class Application {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne(cascade = CascadeType.REFRESH)
private Customer customer;
}
与父抽象实体有关系:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "customers")
public abstract class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
还有子实体:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class SpecificCustomer extends Customer {
private String title;
}
我尝试搜索字段:
@Service
@RequiredArgsConstructor
public class UserSearchRepository {
private final EntityManager entityManager;
private final PredicateUtils predicate;
public void search() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Application> criteriaQuery = criteriaBuilder.createQuery(Application.class);
Root<Application> root = criteriaQuery.from(Application.class);
Join<Application, Customer> applicationCustomerJoin = root.join(Application_.CUSTOMER, JoinType.LEFT);
Predicate[] predicates = {
predicate.like(applicationCustomerJoin.get(Customer_.NAME), "some name") // it works
// predicate.like(applicationCustomerJoin.get(SpecificCustomer_.TITLE), "some title") // it doesn't work
};
criteriaQuery.select(root).where(predicates);
TypedQuery<Application> query = entityManager.createQuery(criteriaQuery);
List<Application> result = query.getResultList();
System.out.println("test:");
System.out.println(result);
}
@PostConstruct
void init() {
this.search();
}
}
当我按父项中存在的字段进行搜索时,它起作用了:
predicate.like(applicationCustomerJoin.get(Customer_.NAME), "some name")
但是当我从 child 按字段搜索时它不起作用:
predicate.like(applicationCustomerJoin.get(SpecificCustomer_.TITLE), "some title")
异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userSearchRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [title] on this ManagedType [my.Customer]
...
Caused by: java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [title] on this ManagedType [my.Customer]
at my.UserSearchRepository.search(UserSearchRepository.java:32) ~[classes/:na]
我无法更改模型的设计。
我发现我可以在第一个连接上使用方法 treat
并创建具有特定类型的第二个连接:
Join<Application, Customer> applicationCustomerJoin = root.join(Application_.CUSTOMER, JoinType.LEFT);
Join<Application, SpecificCustomer> applicationSpecificCustomerJoin = criteriaBuilder.treat(applicationCustomerJoin, SpecificCustomer.class);
Predicate[] predicates = {
predicate.like(applicationSpecificCustomerJoin.get(SpecificCustomer_.TITLE), "some title")
};
我有根实体:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "applications")
public class Application {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne(cascade = CascadeType.REFRESH)
private Customer customer;
}
与父抽象实体有关系:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "customers")
public abstract class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
还有子实体:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class SpecificCustomer extends Customer {
private String title;
}
我尝试搜索字段:
@Service
@RequiredArgsConstructor
public class UserSearchRepository {
private final EntityManager entityManager;
private final PredicateUtils predicate;
public void search() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Application> criteriaQuery = criteriaBuilder.createQuery(Application.class);
Root<Application> root = criteriaQuery.from(Application.class);
Join<Application, Customer> applicationCustomerJoin = root.join(Application_.CUSTOMER, JoinType.LEFT);
Predicate[] predicates = {
predicate.like(applicationCustomerJoin.get(Customer_.NAME), "some name") // it works
// predicate.like(applicationCustomerJoin.get(SpecificCustomer_.TITLE), "some title") // it doesn't work
};
criteriaQuery.select(root).where(predicates);
TypedQuery<Application> query = entityManager.createQuery(criteriaQuery);
List<Application> result = query.getResultList();
System.out.println("test:");
System.out.println(result);
}
@PostConstruct
void init() {
this.search();
}
}
当我按父项中存在的字段进行搜索时,它起作用了:
predicate.like(applicationCustomerJoin.get(Customer_.NAME), "some name")
但是当我从 child 按字段搜索时它不起作用:
predicate.like(applicationCustomerJoin.get(SpecificCustomer_.TITLE), "some title")
异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userSearchRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [title] on this ManagedType [my.Customer]
...
Caused by: java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [title] on this ManagedType [my.Customer]
at my.UserSearchRepository.search(UserSearchRepository.java:32) ~[classes/:na]
我无法更改模型的设计。
我发现我可以在第一个连接上使用方法 treat
并创建具有特定类型的第二个连接:
Join<Application, Customer> applicationCustomerJoin = root.join(Application_.CUSTOMER, JoinType.LEFT);
Join<Application, SpecificCustomer> applicationSpecificCustomerJoin = criteriaBuilder.treat(applicationCustomerJoin, SpecificCustomer.class);
Predicate[] predicates = {
predicate.like(applicationSpecificCustomerJoin.get(SpecificCustomer_.TITLE), "some title")
};