java入门学习(六)

在dao层和service层,每个子类都要自己去重复实现很多同样的内容,这个是需要优化的,武器就是泛型。

dao层改造后的结构如下:

              接口<----------------------------实现类

父       BaseDao<---------------------BaseDaoImpl

                   ^                                                 ^

继承   UserDao<----------------------UserDaoImpl

 

这样,所有Dao要实现的公共接口可以定义在BaseDao中,所有Dao实现类要实现的公用方法,可以在BaseDaoImpl中实现。

PK使用泛型是考虑有些系统表的主键使用的是integer(自增或用sequence),有些系统是使用的string(多用GUID)

从第五章改造后的代码如下:

BaseDao.java

package mybatistest.dao;

import java.io.Serializable;

public interface BaseDao<T, PK extends Serializable> {
	public T getByID(PK id);
}


UserDao.java

package mybatistest.dao;

import mybatistest.entity.User;

public interface UserDao extends BaseDao<User, String>{

}


BaseDaoImpl.java

package mybatistest.dao.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;

import mybatistest.dao.BaseDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public abstract class BaseDaoImpl<T, PK extends Serializable> implements
		BaseDao<T, PK> {
	protected SqlSessionFactory sqlSessionFactory;

	public BaseDaoImpl() {
		String resource = "mybatis-configuration.xml";
		try {
			InputStream inputStream = Resources.getResourceAsStream(resource);
			sqlSessionFactory = new SqlSessionFactoryBuilder()
					.build(inputStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public T getByID(PK id) {
		return null;
	}
}


UserDaoImpl.java

package mybatistest.dao.impl;

import mybatistest.dao.UserDao;
import mybatistest.entity.User;

public class UserDaoImpl extends BaseDaoImpl<User, String> implements UserDao {

	public UserDaoImpl(){
		super();
	}
	
	public User getByID(String id) {
		return sqlSessionFactory.openSession().selectOne(
				"mybatistest.mapper.User.getByID",id);
	}
		
}


Service层类似,此处不再贴出代码了。

Test.java的代码不用改,运行一下,结果同第五章。

虽然运行结果同第五章,但实际上已发生了很大的变化。因为只是举例,所以一是Dao中写的方法少,二是Dao少。当实际应用时,就会有很多的相同的方法和很多的Dao。这样,我们就可以把公共的在父接口和父实现类中定义或实现。

举个简单的例子:

上面在UserDaoImpl.java中,仍然覆写了getByID的方法,按这个思路,每个子类还都要写,那我们能不能在BaseDaoImpl中使用公共的方法来实现呢?答案是肯定的:

两种思路:

1、父类能够得到每个子类的泛型的className,就可以这样:

首先,我们要规划一下mapper中的namespace,每个mapper.xml中的namespace定义成与子类泛型具体类的全名,如user.xml改为如下:

<mapper namespace="mybatistest.entity.User">

然后,就可以在BaseDaoImpl中实现公共的方法了:

package mybatistest.dao.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;

import mybatistest.dao.BaseDao;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public abstract class BaseDaoImpl<T, PK extends Serializable> implements
		BaseDao<T, PK> {
	protected SqlSessionFactory sqlSessionFactory;
	private Class<T> clazz;
	

	public BaseDaoImpl() {
		String resource = "mybatis-configuration.xml";
		try {
			InputStream inputStream = Resources.getResourceAsStream(resource);
			sqlSessionFactory = new SqlSessionFactoryBuilder()
					.build(inputStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.clazz = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		
	}

	public T getByID(PK id) {
		String methodName = Thread.currentThread().getStackTrace()[1]
				.getMethodName();
		return sqlSessionFactory.openSession()
				.selectOne(clazz.getName() + "." + methodName, id);
	}
}


这样,UserDaoImpl就可以删除getByID这个方法,使用父类的方法:

package mybatistest.dao.impl;

import mybatistest.dao.UserDao;
import mybatistest.entity.User;

public class UserDaoImpl extends BaseDaoImpl<User, String> implements UserDao {

	public UserDaoImpl(){
		super();
	}
		
}


2、第二种方式父类定义一个String的mapper变量,由各子类在构造方法中,设置该子类对应的mapper的namespace,具体就不贴代码了。这种灵活性高一些,但麻烦的是每个子类都要在构造方法中去设置这个变量的值。当然,后面考虑更多的公共方法抽取到父类中实现,都可以按这种思路,比如前面说的对应的表名、主键名等,这样就可以实现一个公共的mapper文件,通过动态SQL,来实现所有的表的基本的CURD。不过这种方式是好,还是不好,可能也存在一些争论吧。

 

后面,就要开始学习Spring了,这块以前只是很简单的了解了一下,现在看了一下Spring,内容更多了,包括ORM、Bean的容器管理,还有WEB和MVC等,感觉是要往一整套的解决方案走的节奏啊。不过不要强大完整以后往商业化走啊。

 

 


 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值