考虑到项目将在全省各市部署,预想到在条件允许的市需要调其他市的档案,因此希望DAO能针对接口编程,方便以后扩展以及适应不同的市。
于是在SpringSide的examples.miniweb上作了些修改,希望能够抛砖引玉,更希望各位批评指正。
将IdEntity改为EntityObject,希望以后所有实体都继承它。Id不一定放在这,但要重写equals和hashCode等。
package org.springside.examples.miniweb.entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
* 统一定义id的entity基类.
*
* 基类统一定义id的属性名称、数据类型、列名映射及生成策略.
* 子类可重载getId()函数重定义id的列名映射和生成策略.
*
* @author calvin
*/
//JPA 基类的标识
@MappedSuperclass
public abstract class EntityObject {
protected Long id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
//@GeneratedValue(strategy = GenerationType.SEQUENCE)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
@Override
public boolean equals(Object o) {
return o != null && o.getClass().equals(this.getClass())
&& EqualsBuilder.reflectionEquals(this, o);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
}
定义DAO的通用接口,如下,还有很多常用通用的没有写出来。
package org.springside.examples.miniweb.dao;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import org.springside.examples.miniweb.entity.EntityObject;
/**
* 通用DAO接口<br>
* 在能用此接口完成功能时,不必再派生出子接口<br>
* 在此接口不能满足要求时,派生出相应的子接口<br>
*
* @see org.springside.examples.miniweb.dao.security.RoleDao
* @see org.springside.examples.miniweb.dao.security.ResourceDao
*
* @author langshao
*
*/
public interface GenericDao {
/**
* 根据实体的class及id获取相应的实体
*
* @param <T>
* @param entityClass 实体的class, 如 <code>User.class</code>
* @param id 当为 <code>null</code> 时返回 <code>null</code>
* @return 找到则返回相应的实体, 找不到时返回 <code>null</code>
*/
<T extends EntityObject> T get(Class<T> entityClass, Serializable id);
/**
* 根据实体的class获取所有的实体
*
* @param <T>
* @param entityClass 实体的class, 如 <code>User.class</code>
* @return 没有数据时返回空的 List
*/
<T extends EntityObject> List<T> getAll(Class<T> entityClass);
/**
* 新增或更新实体<br>
* 当entity的id为 <code>null</code> 时新增, 否则更新
*
* @param entity 当为 <code>null</code> 时不保存
*/
void saveOrUpdate(EntityObject entity);
/**
* 批量新增或更新实体<br>
* 当entity的id为 <code>null</code> 时新增, 否则更新
*
* @param entities 当entities为 <code>null</code> 时不保存
* @exception IllegalArgumentException entities的成员含有 <code>null</code>
* 时会抛出异常
*/
void saveOrUpdateAll(Collection<? extends EntityObject> entities)
throws IllegalArgumentException;
/**
* 删除实体
*
* @param entity 当为 <code>null</code> 时不删除
*/
void delete(EntityObject entity);
/**
* 批量删除实体
*
* @param entities 当entities为 <code>null</code> 时不删除
* @exception IllegalArgumentException entities的成员含有 <code>null</code>
* 时会抛出异常
*/
void deleteAll(Collection<? extends EntityObject> entities)
throws IllegalArgumentException;
}
一个简单的实现类如下,我是比较喜欢用HibernateTemplate。
package org.springside.examples.miniweb.dao.impl;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import org.springside.examples.miniweb.dao.GenericDao;
import org.springside.examples.miniweb.entity.EntityObject;
/**
* 通用DAO实现
*
* @author langshao
*
*/
@Repository
public class GenericDaoImpl extends HibernateDaoSupport implements GenericDao {
/**
* 为了使sessionFactory能自动注入而写了这个方法
*
* @param sessionFactory
*/
@Autowired
public void setSessionFactory4Autowired(SessionFactory sessionFactory) {
this.setSessionFactory(sessionFactory);
}
@SuppressWarnings("unchecked")
public <T extends EntityObject> T get(Class<T> entityClass, Serializable id) {
if (id != null)
return (T) getHibernateTemplate().get(entityClass, id);
return null;
}
@SuppressWarnings("unchecked")
public <T extends EntityObject> List<T> getAll(Class<T> entityClass) {
return getHibernateTemplate().loadAll(entityClass);
}
public void saveOrUpdate(EntityObject entity) {
if (entity != null) {
getHibernateTemplate().saveOrUpdate(entity);
}
}
public void saveOrUpdateAll(Collection<? extends EntityObject> entities)
throws IllegalArgumentException {
if (entities != null && !entities.isEmpty()) {
getHibernateTemplate().saveOrUpdateAll(entities);
}
}
public void delete(EntityObject entity) {
if (entity != null) {
getHibernateTemplate().delete(entity);
}
}
public void deleteAll(Collection<? extends EntityObject> entities)
throws IllegalArgumentException {
if (entities != null) {
getHibernateTemplate().deleteAll(entities);
}
}
}
在删除角色时,需要将相应的关联表也删除,因此角色需要重写delete的实现,为了方便自动注入,建立一个新的接口:
package org.springside.examples.miniweb.dao.security;
import org.springside.examples.miniweb.dao.GenericDao;
/**
* 角色DAO接口
*
* @author langshao
*/
public interface RoleDao extends GenericDao {
}
实现如下:
package org.springside.examples.miniweb.dao.security.impl;
import java.util.List;
import org.springframework.stereotype.Repository;
import org.springside.examples.miniweb.dao.impl.GenericDaoImpl;
import org.springside.examples.miniweb.dao.security.RoleDao;
import org.springside.examples.miniweb.entity.EntityObject;
import org.springside.examples.miniweb.entity.security.User;
/**
* 角色DAO实现
*
* @author langshao
*
*/
@Repository
public class RoleDaoImpl extends GenericDaoImpl implements RoleDao {
private static final String QUERY_USER_BY_ROLEID = "select u from User u left join u.roleList r where r.id = ?";
/**
* 重载函数,因为Role中没有建立与User的关联,因此需要以较低效率的方式进行删除User与Role的多对多中间表.
*/
@Override
@SuppressWarnings("unchecked")
public void delete(EntityObject role) {
// 查询出拥有该角色的用户,并删除该用户的角色.
List<User> users = getHibernateTemplate().find(QUERY_USER_BY_ROLEID,
role.getId());
for (User u : users) {
u.getRoleList().remove(role);
}
super.delete(role);
}
}
这样做之后,GenericDao 的 @Autowired 便会报错,以 RoleDaoTest 来说明如何解决之。
在applicationContext-test.xml中加入一个bean:
<bean id="genericDao" class="org.springside.examples.miniweb.dao.impl.GenericDaoImpl" />
然后RoleDaoTest如下写:
package org.springside.examples.miniweb.integration.dao.security;
import javax.annotation.Resource;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springside.modules.test.DataUtils;
import org.springside.modules.test.spring.SpringTxTestCase;
import org.springside.examples.miniweb.dao.GenericDao;
import org.springside.examples.miniweb.dao.security.RoleDao;
import org.springside.examples.miniweb.entity.security.Role;
import org.springside.examples.miniweb.entity.security.User;
/**
* UserDao的集成测试用例,测试ORM映射及特殊的DAO操作.
*
* @author calvin
*/
public class RoleDaoTest extends SpringTxTestCase {
@Autowired
private RoleDao roleDao;
@Resource(name = "genericDao")
private GenericDao userDao;
/**
* 测试删除角色时删除用户-角色的中间表.
*/
@Test
public void deleteRole() {
//新增测试角色并与admin用户绑定.
Role role = new Role();
role.setName(DataUtils.randomName("Role"));
roleDao.saveOrUpdate(role);
User user = userDao.get(User.class, 1L);
user.getRoleList().add(role);
userDao.saveOrUpdate(user);
flush();
int oldJoinTableCount = countRowsInTable("SS_USER_ROLE");
int oldUserTableCount = countRowsInTable("SS_USER");
//删除用户角色, 中间表将减少1条记录,而用户表应该不受影响.
roleDao.delete(role);
flush();
int newJoinTableCount = countRowsInTable("SS_USER_ROLE");
int newUserTableCount = countRowsInTable("SS_USER");
assertEquals(1, oldJoinTableCount - newJoinTableCount);
assertEquals(0, oldUserTableCount - newUserTableCount);
}
}
再举个扩充通用接口的例子:
package org.springside.examples.miniweb.dao.security;
import java.util.List;
import org.springside.examples.miniweb.dao.GenericDao;
import org.springside.examples.miniweb.entity.security.Resource;
/**
* 受保护资源对象的DAO接口
*
* @author langshao
*/
public interface ResourceDao extends GenericDao {
/**
* 查询URL类型的资源并预加载可访问该资源的授权信息.
*/
List<Resource> getUrlResourceWithAuthorities();
}
实现如下:
package org.springside.examples.miniweb.dao.security.impl;
import java.util.List;
import org.springframework.stereotype.Repository;
import org.springside.examples.miniweb.dao.impl.GenericDaoImpl;
import org.springside.examples.miniweb.dao.security.ResourceDao;
import org.springside.examples.miniweb.entity.security.Resource;
/**
* 受保护资源对象的DAO实现
*
* @author langshao
*/
@Repository
public class ResourceDaoImpl extends GenericDaoImpl implements ResourceDao {
public static final String QUERY_BY_RESOURCETYPE_WITH_AUTHORITY = "select distinct r from Resource r "
+ "left join fetch r.authorityList WHERE r.resourceType=? ORDER BY r.position ASC";
@SuppressWarnings("unchecked")
public List<Resource> getUrlResourceWithAuthorities() {
return getHibernateTemplate().find(
QUERY_BY_RESOURCETYPE_WITH_AUTHORITY,
Resource.URL_TYPE);
}
}
这样做主要是想针对接口编程,还有就是不想每新增一个Entity就要增加一个DAO,只要通用的够用就不用再写了。
Write less, do more.
分享到:
相关推荐
SpringSide的Hibernate封装是针对Spring和Hibernate整合时的一种优化实践,旨在提高开发效率和代码的可维护性。它通过三层封装来实现对Hibernate操作的便捷和类型安全。 第一层是HibernateGenericDao,它是基于...
3. **数据访问层**:支持多种ORM框架,如Hibernate和MyBatis,提供统一的DAO接口,降低了数据访问层的复杂性。 4. **RESTful API**:通过Spring MVC实现RESTful服务,方便前后端分离的开发模式。 四、使用场景与...
源码中可以看到 Spring 的依赖注入(DI)和面向切面编程(AOP)的广泛应用,以及对 SpringMVC、Spring Data、Spring Security 等子框架的集成。 1. SpringMVC:负责 Web 层的处理,通过 HandlerMapping 和 ...
4. **最佳实践**:Springside遵循了许多Java开发的最佳实践,如约定优于配置、面向接口编程、依赖注入等,有助于提升代码质量和可维护性。 5. **持续集成**:项目支持Maven构建,并提供了持续集成的配置模板,方便...
SpringSide4参考手册是一份详尽的文档,涵盖了使用SpringSide4.0版本开发应用时可能会用到的各种技术组件和模块。SpringSide是一个开源的Java开发平台,它集成了Spring框架和大量实用的组件,以方便开发人员构建复杂...
7. **国际化支持**:SpringSide 3.0 支持多语言环境,通过ResourceBundle和Spring的MessageSource接口,可以方便地实现应用的国际化。 8. **安全控制**:Spring Security(前身Acegi Security)被集成到SpringSide ...
本资料将由浅入深,逐步解析springside的核心概念和技术,以期让初学者也能顺利上手。 springside的核心特性包括: 1. **模块化设计**:springside采用模块化设计,将项目划分为多个独立的模块,如核心模块、安全...
SpringSide4框架简单使用 sprindside4只写一个简单的DAO接口,日后再根据需要添加方法定义。不需要Dao implements
在深入理解SpringSide之前,我们首先需要了解Spring Framework,这是一个广泛使用的Java企业级应用开发框架,它为开发者提供了诸如依赖注入、面向切面编程、数据访问、事务管理等核心功能。 SpringSide项目的核心...
例如,它强调面向接口编程、依赖注入、单元测试等原则,使得代码更加松耦合,易于维护。 四、开发效率提升 SpringSide 4.1.0.GA包含了一套代码生成工具,可以自动生成常见的CRUD操作,减少了重复劳动,提高了开发...
SpringSide项目始于对Spring Framework的深度理解和实践,它的核心在于简化Spring的使用,让开发者能够更快速、更高效地构建企业级应用程序。4.0.0.GA版本是该项目的一个稳定发布,代表着经过充分测试和验证的成熟...
5. **AOP(面向切面编程)支持**: Springside提供了对Spring AOP的集成,允许开发者定义切面,实现如日志记录、事务管理等功能,增强了代码的可复用性。 6. **单元测试**:Springside鼓励并简化了单元测试的编写,...
它集合了最佳实践,包括Maven构建系统、JUnit测试框架、AspectJ切面编程、Hibernate ORM工具等,以帮助开发者快速上手Spring应用。在本文中,我们将深入探讨SpringSide示例Quickstart的Eclipse工程,了解其结构和...
pom.xml配置 ...mvn install:install-file -DgroupId=org.springside -DartifactId=springside-core -Dversion=4.2.2.GA -Dfile=./springside-core-4.2.2.GA.jar -Dpackaging=jar -DgeneratePom=true
springside-extension模块是针对Spring框架的扩展,包含了一些实用的工具类和配置,如日志管理、缓存支持、安全控制等。这些扩展使得开发者能够更便捷地实现常见的业务需求,降低了开发难度。 五、springside-...
《深入解析springside4.2.3-GA.jar:Java开发者的宝藏库》 在Java开发领域,SpringSide框架以其高效、灵活和强大的特性深受开发者喜爱。本文将围绕springside4.2.3-GA.jar这个核心组件,探讨其在Java应用中的重要...
SpringSide 4的showcase还会展示如何整合其他Spring模块,比如Spring Security进行权限管理,Spring Data进行数据访问,Spring AOP实现切面编程,以及Spring Test进行单元测试和集成测试。所有这些都将帮助开发者...
### springside3.3.4使用方法与SSH整合详解 #### 一、Springside简介 Springside项目是基于Spring框架的一个应用架构示例,它提供了一套完整的开发模式来构建企业级Java Web应用程序。Springside 3.3.4版本作为一...
SpringSide3则围绕这些核心特性,通过实例解析,让开发者能够快速上手Spring。 二、依赖注入 依赖注入是Spring框架的核心,它解决了对象之间的耦合问题,降低了代码的复杂度。在SpringSide3中,你会了解到如何通过...
SpringSide3.3.4 安装部署详解 SpringSide3.3.4 安装部署是指在计算机上安装和部署 SpringSide3.3.4 软件的过程。在这个过程中,我们需要使用 Maven 工具来生成项目模板,安装 mini-web 应用程序,并配置相应的...