DAO功能有限的接口
我们的DAO里有这么一个接口:
/**
* 按属性查找对象列表,匹配方式为相等.
*/
public List<T> findBy(final String propertyName, final Object value) {
assert StringUtils.isNotBlank(propertyName);
String jpql = "from " + getEntityClass().getName() + " t where t." + propertyName + "=?";
return find(jpql, value);
}
如,我们需要查找用户状态为已开启的用户列表时,就会使用这个方法。
新的需求
今天,我们来谈谈另外一个需求,假设角色与权限是单向关联的,我们需要查找拥有权限A的所有角色。
以前的解决方案
以往我们要实现这个功能,一般我们需要在RoleDao里写一个方法,如listByPermissionName,实现可能就通过一个JPQL解决了:
/**
* 获取拥有指定权限的角色列表.
*/
public List<User> listByPermissionName(final String permissionName) {
// 注意,当有join子句时,必须要有select子句,不然返回的结果将不是Role类型。
String jpql = "select distinct r from " + Role.class.getName() + " r left join r.permissions p where p.name=?";
return super.find(jpql, permissionName);
}
便利的解决方案
现在我们碰到了很多个这种类似需求,所以,可不可以dao父类方法可以解决这个问题呢?
所以,这两个接口就产生了:
/**
* 按集合属性里的某个属性查找对象列表,匹配方式为相等.
*
* @param propertyName 集合属性名
* @param nestedPropertyName 集合属性对象的指定属性
* @param value 匹配值
*/
public List<T> findBy(final String propertyName, final String nestedPropertyName, final Object value) {
assert StringUtils.isNotBlank(propertyName);
assert StringUtils.isNotBlank(nestedPropertyName);
String jpql = "select distinct t from " + getEntityClass().getName() + " t left join t." + propertyName
+ " p where p." + nestedPropertyName + "=?";
return find(jpql, value);
}
/**
* 按集合属性里的某个属性查找唯一对象,匹配方式为相等.
*
* @param propertyName 集合属性名
* @param nestedPropertyName 集合属性对象的指定属性
* @param value 匹配值
*/
public T findUniqueBy(final String propertyName, final String nestedPropertyName, final Object value) {
assert StringUtils.isNotBlank(propertyName);
assert StringUtils.isNotBlank(nestedPropertyName);
String jpql = "select distinct t from " + getEntityClass().getName() + " t left join t." + propertyName
+ " p where p." + nestedPropertyName + "=?";
return findUnique(jpql, value);
}
现在,要实现上面那个功能,只需要在RoleManager里调用IdEntityDao里的这个方法就OK了:
/**
* 获取拥有指定权限的角色列表.
*/
@Transactional(readOnly = true)
public List<User> listByPermissionName(final String permissionName) {
return getEntityDao().findBy("permissions", "name", permissionName);
}
- 我们的dao基类代码都只考虑no fetch的情况,所有需要加载延迟属性的方法都需要自己再写dao方法实现 ,这在目前所有的框架里都是这样的。是否考虑提供findWithLazyPropertiesBy(String propertyName, Object value, String[] fetchedPropertyNames); 的方法,有待讨论
- 这个方法确实只考虑到一级集合属性的情况。可以考虑提供findByMultiLevelProperty(String multiLevelPropertyName, Object value); 的方法,这样使用(在RoleManager中):List<Role> role = getEntityDao().findBy("permissions.resources.name", "资源名称");
所提供的方法有几个问题