2008-05-14
又一个DynamicDao
模型如下:
@Entity
public class User extends BaseEntry{
private String name;
private int age;
@OneToMany(mappedBy = "user", cascade=CascadeType.ALL)
private Set<Article> articles = new HashSet<Article>();
.......
}
@Entity
public class Article extends BaseEntry{
private String title;
private String content;
@ManyToOne
private User user;
….
}
将Dao继承GenericDao,如:
public interface UserDao extends GenericDao<User, Integer>{
}
public interface ArticleDao extends GenericDao<Article, Integer>{
}
然后在配置文件中增加如下代码:
<bean id="parentDao" class="com.dynamicDao.GenericDaoFactoryBean" abstract="true" p:sessionFactory-ref="sessionFactory"/> <bean id="userDao" parent="parentDao" p:daoInterface="com.dynamicDao.fixtures.dao.UserDao"> </bean> <bean id="articleDao" parent="parentDao" p:daoInterface="com.dynamicDao.fixtures.dao.ArticleDao"> </bean>
在Service中注入Dao即可,如:
public UserService{
@Autowired
UserDao userDao;
...
}
基本功能:
GenericDao继承Session接口,另外还继承以下接口:
public interface TypedSession<T, PK extends Serializable> {
Criteria createCriteria();
T load(PK pk);
T load(PK pk, LockMode lockMode);
T get(PK pk);
T get(PK pk, LockMode lockMode);
}
对应着Session中需要实体类型的方法,如T load(PK pk)对应着Session#load(Class entityClass, Serializable pk);
public interface SimpleCriteria<T> {
public SimpleCriteria eq(String property, Object value);
public SimpleCriteria like(String property, Object value);
public SimpleCriteria gt(String property, Object value);
public SimpleCriteria order(String property, boolean... asc);
public SimpleCriteria include(String...associations);
public SimpleCriteria limit(int limit);
public SimpleCriteria page(int pageNum, int pageSize);
public T first();
public List<T> all();
}
简单地包装了Criteria(还需完善),使用如下:
userDao.eq("name", "tester1").first()
//eager loading
userDao.eq("id", 1).include("articles").first()
public interface BaseDao<T, PK extends Serializable>{
Class getEntityClass();
Session getSession();
SessionFactory getSessionFactory();
Collection<T> findByHsql(String hsql, Object...args);
SimpleCriteria createSimpleCriteria();
}
有些简陋,因为GenericDao已经继承Session。
动态查询:
在UserDao加入以下方法即可:
public interface UserDao extends GenericDao<User, Integer>{
List<User> findByAge(int age, SimpleCriteria sc);
User findByNameAndAge(Object...args);
}
SimpleCriteria是用来增加一些额外的条件,只要将SimpleCriteria作为最后一个参数即可,也可以不要,如List<User> findByAge(int age)。
目前不支持关联查询,如ArticleDao.findByUserId(int id)
自定义接口:
- 先定义一个接口,如:
public interface CustomDao { List<Article> articlesAboutPageTest(); } -
然后实现:
public class CustomDaoImpl implements CustomDao, GenericDaoAware{ private GenericDao genericDao; public List<Article> articlesAboutPageTest() { return this.genericDao.eq("title", "pageTest").all(); } public void setGenericDao(GenericDao genericDao) { this.genericDao = genericDao; } } 注意这里继承了GenericDaoAware,用来注入GenericDao -
在配置文件中增加:
<bean id="articleDao" parent="parentDao" p:daoInterface="com.dynamicDao.fixtures.dao.ArticleDao"> <property name="advices"> <list> <bean class="com.dynamicDao.fixtures.dao.CustomDaoImpl"/> </list> </property> </bean> -
最后一步就是让你的Dao继承CustomerDao, 如:
public interface ArticleDao extends GenericDao<Article, Integer>, CustomDao{ }
- 14:57
- 浏览 (88)
- 论坛浏览 (951)
- 评论 (4)
- 相关推荐
评论
studyworks
2008-05-14
回复
实现Query Annotation的主要代码如下:
public class AnnotationQueryInterceptor extends AbstractMethodInterceptor{
public Object invoke(MethodInvocation mi) throws Throwable {
Query query = mi.getMethod().getAnnotation(Query.class);
if(null != query){
if(Collection.class.isAssignableFrom(mi.getMethod().getReturnType())){
return super.genericDao.findByHsql(query.value(), mi.getArguments());
}
else{
return super.genericDao.findFirstByHsql(query.value(), mi.getArguments());
}
}
return mi.proceed();
}
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Query {
String value() default "";
}
最后在GenericDaoFactoryBean的方法initInternalAdvices() 中加入addAdvice(new AnnotationQueryInterceptor())即可;
void initInternalAdvices() {
addAdvice(new SessionInterceptor());
addAdvice(new SimpleCriteriaInterceptor());
addAdvice(new TypedSessionInterceptor());
addAdvice(new DynamicFinderInterceptor());
addAdvice(new AnnotationQueryInterceptor());
}
要扩展其他接口,如ActiveRecord中的find_or_create_by等功能也比较简单。
studyworks
2008-05-14
回复
Norther 写道
没看出来dynamic在哪?就是自己实现了一套Criteria,而且GenericDao都继承Session了,等于把Session整个都暴露给调用dao的人了,那还要dao干螃蟹?直接访问session不就完了,不明白这个dynamic dao的设是什么目的。
其实直接实现Session只是一种方式(有点模仿ActiveRecord的意思),完全可以实现其他的GenericDao的接口,如SpringSide的EntityDao<T>接口,或者自己写一个通用的接口。
另外刚才实现了主题:模仿Warp Dynamic Finder的Hibernate Dynamic Dao里面的Query 注解功能,使用如下:
public interface ArticleDao extends GenericDao<Article, Integer>{
@Query("from Article where title = ?")
Article getFirstArticleAbout(String title);
}
另外,请看看代码,可能有些东西我没有表达清楚。
多谢回复.
最近加入圈子
最新评论
-
又一个DynamicDao
呵呵,老大你写的东东,不错。我学习了(刚刚一新手哈!) 不过,要是再写一点注释就 ...
-- by heshencao -
又一个DynamicDao
实现Query Annotation的主要代码如下: public class ...
-- by studyworks -
又一个DynamicDao
Norther 写道 没看出来dynamic在哪?就是自己实现了一套Crite ...
-- by studyworks -
又一个DynamicDao
没看出来dynamic在哪?就是自己实现了一套Criteria,而且Generi ...
-- by Norther







评论排行榜