这种写法一般都会在基类中看到,而且是使用了JAVA泛型的,比如我们J2EE中的BaseDAO什么的,请看代码,其实简写了,分开写就明了了。在BaseDao中经常写一个单独的方法,如下:
private Class<?> clz;
public Class<?> getClz() {
if(clz==null) {
//获取泛型的Class对象
clz = ((Class<?>)
(((ParameterizedType)(this.getClass().getGenericSuperclass())).getActualTypeArguments()[0]));
}
return clz;
}
上述方法能够返回泛型的实际class类型
测试方式:
基类
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public abstract class SuperClass<T> {
private Class<T> beanClass;
@SuppressWarnings("unchecked")
public SuperClass() {
super();
ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
Type[] types = parameterizedType.getActualTypeArguments();
beanClass = (Class<T>) types[0];
}
public Class<T> getBeanClass() {
return beanClass;
}
public void setBeanClass(Class<T> beanClass) {
this.beanClass = beanClass;
}
public static void main(String[] args) {
SuperClass<Cat> superClass = new SubClass();
System.out.println(superClass.getBeanClass());
}
}
子类:
public class SubClass extends SuperClass<Cat> {
public SubClass() {
super();
}
}
class Cat {
public Cat() {
super();
}
}
得到结果:
class com.stos.test.generic.Cat
对于BaseDao,通常的编辑方法可以使用以下方式:
有一个IBaseDao<T>,作为最原始的公共接口,内部定义了一些简单的增删改查方法,然后是一个BaseDao<T>类,该类实现了IBaseDao<T>接口,并在里面实现了IBaseDao<T>定义的方法,除此之外,该类的内部可以定义一些自己的方法,去直接操作数据库获取结果,比如额外定义了如下的方法:
<span style="white-space:pre"> </span>public Object queryObject(String hql, Object[] args,
Map<String, Object> alias) {
Query query = getSession().createQuery(hql);
setAliasParameter(query, alias);
setParameter(query, args);
return query.uniqueResult();
}
public Object queryObjectByAlias(String hql, Map<String, Object> alias) {
return this.queryObject(hql,null,alias);
}
也就是可以定义多个名称一样的方法,其中有一个是去直接操作数据库的,如上面方法中的第一个方法,然后其他的方法通过重载的方式传递参数去调用这个方法即可如第二个方法。
其次,对于自身实际操作的model类,如User类,可以使用首先定义一个IUserDao接口,该接口继承IBaseDao<User>,从而继承了IBaseDao<User>中定义的方法,IUserDao可以定义自己的准备交给Service调用的方法,如:
public interface IUserDao extends IBaseDao<User>{
/**
* 获取用户的所有角色信息
* @param userId
* @return
*/
public List<Role> listUserRoles(int userId);
/**
* 获取用户的所有角色的id
* @param userId
* @return
*/
public List<Integer> listUserRoleIds(int userId);
/**
* 获取用户的所有组信息
* @param userId
* @return
*/
}
最后定义UserDao,该类继承BaseDao<User>实现IUserDao,由于继承了BaseDao,所以该类内部可以通过this.方法名()直接调用BaseDao中定义的方法,该类中实现IUserDao中定义的要给Service调用的方法,内部实现可以在该类中去直接操作数据库,也可以去通过this.方法名去调用BaseDao中的相应方法来操作数据库,具体视程序的灵活性而定。
public class UserDao extends BaseDao<User> implements IUserDao {
//直接操作数据库
@Override
public List<Role> listUserRoles(int userId) {
String hql = "select ur.role from UserRole ur where ur.user.id=?";
return this.getSession().createQuery(hql).setParameter(0,userId).list();
}
@Override
public List<Integer> listUserRoleIds(int userId) {
String hql = "select ur.role.id from UserRole ur where ur.user.id=?";
return this.getSession().createQuery(hql).setParameter(0,userId).list();
}
<span style="white-space:pre"> </span>//通过BaseDao来进行操作数据库
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public User loadByUsername(String username) {
<span style="white-space:pre"> </span>String hql = "from User where username=?";
<span style="white-space:pre"> </span>return (User)this.queryObject(hql, username);
<span style="white-space:pre"> </span>}
}
最终就可以定义IService以及Service层了,进行相应的dao层调用即可
1、java程序源码方面
(1)IBaseDao接口使用泛型,<T>
public interface IBaseDao<T> {
/**
* 添加对象
* @param t
* @return
*/
public T add(T t);
/**
* 更新对象
* @param t
*/
public void update(T t);
/**
* 根据id删除对象
* @param id
*/
public void delete(int id);
/**
* 根据id加载对象
* @param id
* @return
*/
public T load(int id);
}
(2)BaseDao实现方法,这个方法里面定义了具体的操作通用的dao操作方法
public class BaseDao<T> implements IBaseDao<T> {
private SessionFactory sessionFactory;
/**
* 创建一个Class的对象来获取泛型的class
* 如返回:class org.konghao.basic.model.User
*/
private Class<?> clz;
public Class<?> getClz() {
if(clz==null) {
//获取泛型的Class对象
clz = ((Class<?>)
(((ParameterizedType)(this.getClass().getGenericSuperclass())).getActualTypeArguments()[0]));
}
return clz;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Inject
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
/* (non-Javadoc)
* @see org.konghao.baisc.dao.IBaseDao#add(java.lang.Object)
*/
@Override
public T add(T t) {
getSession().save(t);
return t;
}
<span style="white-space:pre"> </span>public <N extends Object>List<N> listBySql(String sql, Object[] args, Class<?> clz,
<span style="white-space:pre"> </span>boolean hasEntity) {
<span style="white-space:pre"> </span>return this.listBySql(sql, args, null, clz, hasEntity);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public <N extends Object>List<N> listBySql(String sql, Object[] args,
<span style="white-space:pre"> </span>Map<String, Object> alias, Class<?> clz, boolean hasEntity) {
<span style="white-space:pre"> </span>sql = initSort(sql);
<span style="white-space:pre"> </span>SQLQuery sq = getSession().createSQLQuery(sql);
<span style="white-space:pre"> </span>setAliasParameter(sq, alias);
<span style="white-space:pre"> </span>setParameter(sq, args);
<span style="white-space:pre"> </span>if(hasEntity) {
<span style="white-space:pre"> </span>sq.addEntity(clz);
<span style="white-space:pre"> </span>} else
<span style="white-space:pre"> </span>sq.setResultTransformer(Transformers.aliasToBean(clz));
<span style="white-space:pre"> </span>return sq.list();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>。。。。。。。。
}
2、测试源码java层面,对上面的BaseDao'进行测试,针对某一个dao,如针对用户信息User操作的UserDao
(1)IUserDao,定义一个User类相关的IUserDao接口,该接口继承IBaseDao,并指定泛型为model层的User,并且里面写自己的要得到的数据的方法,所有的泛型制定为User
public interface IUserDao extends IBaseDao<User> {
List<User> list(String string, Object[] objects);
List<User> list(String string, Object[] objects, Map<String, Object> alias);
Pager<User> find(String string, Object[] objects);
Pager<User> find(String string, Object[] objects, Map<String, Object> alias);
List<User> listUserBySql(String string, Object[] objects, Map<String, Object> alias, Class<User> class1,
boolean b);
List<User> listUserBySql(String string, Object[] objects, Class<User> class1,
boolean b);
Pager<User> findUserBySql(String string, Object[] objects, Class<User> class1,
boolean b);
Pager<User> findUserBySql(String string, Object[] objects,
Map<String, Object> alias, Class<User> class1, boolean b);
}
(2)UserDao继承BaseDao<User>实现IUserDao,内部重写了IUserDao的所有方法,但是在重写的方法内部是用BaseDao<User>类的方法来进行方法的调用也就是UserDao->IUserDao->BaseDao(IBaseDao)->操作数据库
@Repository("userDao")
public class UserDao extends BaseDao<User> implements IUserDao {
@Override
public List<User> listUserBySql(String string, Object[] objects,
Map<String, Object> alias, Class<User> class1, boolean b) {
return super.listBySql(string, objects, alias, class1, b);
}
@Override
public List<User> listUserBySql(String string, Object[] objects,
Class<User> class1, boolean b) {
return super.listBySql(string, objects, class1, b);
}
@Override
public Pager<User> findUserBySql(String string, Object[] objects,
Class<User> class1, boolean b) {
return super.findBySql(string, objects, class1, b);
}
@Override
public Pager<User> findUserBySql(String string, Object[] objects,
Map<String, Object> alias, Class<User> class1, boolean b) {
return super.findBySql(string, objects, alias, class1, b);
}
}
(3)测试类,该类直接对UserDao进行调用即可实现了
public class TestUserDao extends AbstractDbUnitTestCase{
@Inject
private SessionFactory sessionFactory;
@Inject
private IUserDao userDao;
@Before
public void setUp() throws DataSetException, SQLException, IOException {
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));
this.backupAllTable();
}
@Test
// @DatabaseSetup("/t_user.xml")
public void testLoad() throws DatabaseUnitException, SQLException {
IDataSet ds = createDateSet("t_user");
DatabaseOperation.CLEAN_INSERT.execute(dbunitCon,ds);
User u = userDao.load(1);
EntitiesHelper.assertUser(u);
}
@Test(expected=ObjectNotFoundException.class)
public void testDelete() throws DatabaseUnitException, SQLException {
IDataSet ds = createDateSet("t_user");
DatabaseOperation.CLEAN_INSERT.execute(dbunitCon,ds);
userDao.delete(1);
User tu = userDao.load(1);
System.out.println(tu.getUsername());
}
@Test
public void testListByArgs() throws DatabaseUnitException, SQLException {
IDataSet ds = createDateSet("t_user");
DatabaseOperation.CLEAN_INSERT.execute(dbunitCon,ds);
SystemContext.setOrder("desc");
SystemContext.setSort("id");
List<User> expected = userDao.list("from User where id>? and id<?", new Object[]{1,4});
List<User> actuals = Arrays.asList(new User(3,"admin3"),new User(2,"admin2"));
assertNotNull(expected);
assertTrue(expected.size()==2);
EntitiesHelper.assertUsers(expected, actuals);
}
}