Spring 规格标准多重连接?如何?
Spring Specification Criteria Multiple Joins ? How?
我在使用 Spring 项目和 Spring 数据 + 规范 + 标准 api 时遇到了困难。
我将尝试使用我们编写的一般实体来模拟这种情况,以获得简单的示例。
实体:
考虑每个实体的所有属性都传递给下面显示的构造函数
国家(长id,字符串名称,字符串iso)
State(Long id, String name, String iso)
城市(Long id, String name, String iso)
这是我的存储库:
public interface CityRepository extends PagingAndSortingRepository<City, Integer>, JpaSpecificationExecutor<City> {
}
如您所见,我不需要在存储库上实现任何东西
这是我的服务
@Service
@Transactional
public class CityService {
@Autowired
private CityRepository cityRepository;
@Transactional(readOnly = true)
public CityListVO findByNameLike(String name, PageRequest pageRequest) {
name = "%" + name + "%";
if (pageRequest == null) {
List<City> result = cityRepository.findAll(fillGridCriteria(name));
return new CityListVO(1, result.size(), result);
} else {
Page<City> result = cityRepository. findAll(fillGridCriteria(name), pageRequest);
return new CityListVO(result.getTotalPages(), result.getTotalElements(), result.getContent());
}
}
private static Specification<City> fillGridCriteria(String name) {
return new Specification<City>() {
@Override
public Predicate toPredicate(
Root<City> root,
CriteriaQuery<?> query,
CriteriaBuilder builder) {
/*
The current return I can do a like by name, and it works fine.
My problem is if for any reason I need to do multiple joins like the folow jpql:
select ci FROM City ci, State st, Country co where ci.st = st AND st.co = co AND co.name = 'Canada';
How to do this from here ? Inside this method.
How is gonna be the return for this method ?
*/
return builder.like(root.get("name"), name.trim());
}
};
}
}
让我们假设您想要他们的国家/地区名称像 name
的所有城市,并且您有一个关系模型,其中:
Country(Long id, String name, String iso)
State(Long id,Long country, String name, String iso)
City(Long id, Long state, String name, String iso)
谓词:
private static Specification<City> fillGridCriteria(String name) {
return new Specification<City>() {
@Override
public Predicate toPredicate(
Root<City> root,
CriteriaQuery<?> query,
CriteriaBuilder builder) {
return
builder.like(root.get("state").get("country").get("name"), name.trim());
}
};
}
我在使用 Spring 项目和 Spring 数据 + 规范 + 标准 api 时遇到了困难。
我将尝试使用我们编写的一般实体来模拟这种情况,以获得简单的示例。
实体: 考虑每个实体的所有属性都传递给下面显示的构造函数
国家(长id,字符串名称,字符串iso)
State(Long id, String name, String iso)
城市(Long id, String name, String iso)
这是我的存储库:
public interface CityRepository extends PagingAndSortingRepository<City, Integer>, JpaSpecificationExecutor<City> {
}
如您所见,我不需要在存储库上实现任何东西
这是我的服务
@Service
@Transactional
public class CityService {
@Autowired
private CityRepository cityRepository;
@Transactional(readOnly = true)
public CityListVO findByNameLike(String name, PageRequest pageRequest) {
name = "%" + name + "%";
if (pageRequest == null) {
List<City> result = cityRepository.findAll(fillGridCriteria(name));
return new CityListVO(1, result.size(), result);
} else {
Page<City> result = cityRepository. findAll(fillGridCriteria(name), pageRequest);
return new CityListVO(result.getTotalPages(), result.getTotalElements(), result.getContent());
}
}
private static Specification<City> fillGridCriteria(String name) {
return new Specification<City>() {
@Override
public Predicate toPredicate(
Root<City> root,
CriteriaQuery<?> query,
CriteriaBuilder builder) {
/*
The current return I can do a like by name, and it works fine.
My problem is if for any reason I need to do multiple joins like the folow jpql:
select ci FROM City ci, State st, Country co where ci.st = st AND st.co = co AND co.name = 'Canada';
How to do this from here ? Inside this method.
How is gonna be the return for this method ?
*/
return builder.like(root.get("name"), name.trim());
}
};
}
}
让我们假设您想要他们的国家/地区名称像 name
的所有城市,并且您有一个关系模型,其中:
Country(Long id, String name, String iso)
State(Long id,Long country, String name, String iso)
City(Long id, Long state, String name, String iso)
谓词:
private static Specification<City> fillGridCriteria(String name) {
return new Specification<City>() {
@Override
public Predicate toPredicate(
Root<City> root,
CriteriaQuery<?> query,
CriteriaBuilder builder) {
return
builder.like(root.get("state").get("country").get("name"), name.trim());
}
};
}