我正在学习Jpa标准查询,并且不知道如何实现这个:
我有一个名为Restaurant的实体:
@Entity
@Table(name = "t_f2g_restaurant",
uniqueConstraints = @UniqueConstraint(columnNames = { "NAME" }))
public class Restaurant {
@EmbeddedId
@AttributeOverrides(
{ @AttributeOverride(name = "value", column = @Column(name = "ID")) })
private RestaurantIdentity id;
@Column(name = "name")
private String name;
@ElementCollection
@CollectionTable(name = "t_f2g_restaurant_srv_area",
joinColumns = @JoinColumn(name = "RESTAURANT_ID"))
@Column(name = "zip_code")
private List<String> serviceAreas = new ArrayList<String>();
}
现在我想计算按serviceAreas过滤的餐馆,下面是我原生的sql实现:
private boolean delegateToNativeQuery(Address deliveryAddress {
String sqlString = "select count(*) from t_f2g_restaurant r "
+ "where exists (select * from t_f2g_restaurant_srv_area sa "
+ "where sa.zip_code = ? and r.id = sa.restaurant_id) ";
Query query = entityManager.createNativeQuery(sqlString);
query.setParameter(1, deliveryAddress.getZipCode());
return ((Number) query.getSingleResult()).longValue() > 0;
}
但是如何使用条件查询实现它呢?
以下是我的尝试:
private boolean delegateToCriteriaQuery(Address deliveryAddress) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> query = criteriaBuilder.createQuery(Long.class);
Root<Restaurant> restaurant = query.from(Restaurant.class);
Subquery<Long> serviceAreaSubquery = query.subquery(Long.class);
/* This causes an extra t_f2g_restaurant, t_f2g_restaurant_srv_area join
Root<Restaurant> serviceAreaRoot = serviceAreaSubquery
.from(Restaurant.class);
ListJoin<Restaurant, String> serviceAreas = serviceAreaRoot
.joinList("serviceAreas");
serviceAreaSubquery.select(criteriaBuilder.count(serviceAreaRoot))
.where(criteriaBuilder.
//serviceArea is represented by String, so what's the attribute name?
equal(serviceAreas.get("serviceArea"), deliveryAddress.getZipcode()));
query.select(criteriaBuilder.count(restaurant)).
where(criteriaBuilder.exists(serviceAreaSubquery));
return entityManager.createQuery(query).getSingleResult() > 0;
}
答案 0 :(得分:1)
我刚才做到了。希望答案可以帮到某人。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Restaurant> query = criteriaBuilder
.createQuery(Restaurant.class);
Root<Restaurant> restaurants = query.from(Restaurant.class);
Subquery<Restaurant> serviceAreasFiltering = query
.subquery(Restaurant.class);
ListJoin<Object, Object> serviceAreas = serviceAreasFiltering
.correlate(restaurants).joinList("serviceAreas");
//correlate joins t_f2g_restaurant and t_f2g_restaurant_srv_area
serviceAreasFiltering.where(criteriaBuilder.or(
criteriaBuilder.equal(serviceAreas, deliveryAddress.getStreet1()),
//equal against serviceAreas for I use List<String> for serviceAreas
criteriaBuilder.equal(serviceAreas, deliveryAddress.getStreet2())));
query.where(criteriaBuilder.exists(serviceAreasFiltering));
return entityManager.createQuery(query).getResultList();
坦率地说,在这种情况下,我不认为api的标准很容易阅读。我可能不会切换到条件api,除非我需要返回一个餐馆列表(如果使用本机sql查询,我需要编写结果映射器)。