是否有任何已知的方法来使用带有切入点的面向方面注释(或任何其他工作)进行hibernate分页,以在任何给定方法中识别Criteria
并将setFirstResults
和setMaxResults
应用于它GenericDao
API方法?
例如,我想在我的hibernate @Paginate
public List<T> filter(Set<Criterion> filter, Map<String, String> alias){
Criteria criteria = session.createCriteria(type.class);
fillCriteria(criteria, filter, alias);
return criteria.list();
}
实现中应用以下分页:
@Paginate
setFirstResults
注释会在setMaxResults
来电时应用criteria.list()
和@Paginate
。这可能吗?
注意:{{1}}是我想要使用的示例。
答案 0 :(得分:1)
是的,您可以通过 AspectJ 来完成此操作。
这是一个自洽的独立代码示例。您只需复制并粘贴类和方面并运行它即可。我不是使用原始的Hibernate类,而是使用一些虚拟替换,因为我不是Hibernate用户,我也想让它成为一个通用的答案:
虚拟,类似hibernate的接口和类:
package de.scrum_master.app;
public interface Criterion {}
package de.scrum_master.app;
public class MyCriterion implements Criterion {
private String criterion;
public MyCriterion(String criterion) {
this.criterion = criterion;
}
@Override
public String toString() {
return "MyCriterion [criterion=" + criterion + "]";
}
}
package de.scrum_master.app;
import java.util.List;
public interface Criteria {
Criteria add(Criterion criterion);
List list();
Criteria setFirstResult(int firstResult);
Criteria setMaxResults(int maxResults);
}
package de.scrum_master.app;
import java.util.LinkedList;
import java.util.List;
public class MyCriteria implements Criteria {
private List<Criterion> criteria = new LinkedList<>();
@Override
public Criteria add(Criterion criterion) {
criteria.add(criterion);
return this;
}
@Override
public List list() {
return new LinkedList();
}
@Override
public Criteria setFirstResult(int firstResult) {
add(new MyCriterion("first result " + firstResult));
return this;
}
@Override
public Criteria setMaxResults(int maxResults) {
add(new MyCriterion("max results " + maxResults));
return this;
}
@Override
public String toString() {
return "MyCriteria [criteria=" + criteria + "]";
}
}
如您所见,方法setFirstResult(..)
和setMaxResults(..)
通过add(..)
向内部列表添加特殊条件。我这样做是为了以后说明方面的效果。
分页注释:
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Paginate {}
驱动程序应用程序:
package de.scrum_master.app;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Application {
@Paginate
public List filter(Set<Criterion> filter, Map<String, String> alias) {
Criteria criteria = new MyCriteria();
for (Criterion criterion : filter)
criteria.add(criterion);
return criteria.list();
}
public static void main(String[] args) {
Set<Criterion> filterCriteria = new HashSet<>();
filterCriteria.add(new MyCriterion("where"));
filterCriteria.add(new MyCriterion("group by"));
new Application().filter(filterCriteria, null);
}
}
该应用程序包含一个由@Paginate
注释的方法,执行与示例代码类似的操作。它不会调用任何分页方法。这将通过以下方面完成。
分页方面:
package de.scrum_master.aspect;
import java.util.List;
import de.scrum_master.app.Paginate;
import de.scrum_master.app.Criteria;
public aspect PaginationAspect {
Object around(Criteria criteria) :
call(public List Criteria+.list()) &&
cflow(execution(@Paginate * *(..))) &&
target(criteria)
{
System.out.println(thisJoinPoint);
System.out.println("Original criteria: " + criteria);
criteria.setFirstResult(5);
criteria.setMaxResults(10);
System.out.println("Modified criteria: " + criteria);
return proceed(criteria);
}
}
切入点拦截对Criteria+.list()
的调用(+
包括子类),但仅在cflow()
注释的任何执行方法的控制流(@Paginate
)中发出时。调用目标绑定到参数Criteria criteria
,以便在绑定到该切入点的advice方法中使用它。我们需要一个对调用目标的引用,因为我们想要调用它的分页方法。这就是建议的作用,控制台输出清楚地说明了这一点。
控制台输出:
call(List de.scrum_master.app.Criteria.list())
Original criteria: MyCriteria [criteria=[MyCriterion [criterion=group by], MyCriterion [criterion=where]]]
Modified criteria: MyCriteria [criteria=[MyCriterion [criterion=group by], MyCriterion [criterion=where], MyCriterion [criterion=first result 5], MyCriterion [criterion=max results 10]]]
享受!