实现基于接口编程的关键在于DAO是一个代理类, 所以DAO 不该该由用户进行实例化, 应该由框架提供统一的工厂类用来获取DAO. 工厂类中根据DAO类型生成对应的动态代理类返回用户.sql
// Mapper工厂类(负责生成DAO的动态代理对象)
public class MapperFactory {
// SQL会话工厂类
private SqlSessionFactory sqlSessionFactory;
// 经过SQL会话工厂类实例化
public MapperFactory(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
// 根据DAO类型获取DAO的动态代理类
public <T> T getMapper(Class<T> clazz) {
SqlSession session = this.sqlSessionFactory.getSession();
return new MapperProxy(session).getMapper(clazz);
}
}
复制代码
在获取DAO时经过工厂类获取, 此时获取的是DAO的代理类.数据库
UserDAO userDAO = new MapperFactory(sf).getMapper(UserDAO.class);
复制代码
当调用DAO中的接口时, 会自动执行动态代理类中的invoke方法. 在invoke方法中执行数据库操做便可.编程
// Mapper动态代理类
public class MapperProxy implements InvocationHandler {
// SQL会话
private SqlSession sqlSession;
// 经过SQL会话实例化
public MapperProxy(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
// 获取动态代理类
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> clazz) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, this);
}
// 执行接口时进入该方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 接口中方法名称和SQL节点ID相同
String statementId = method.getName();
// 根据方法名称便可获取对应的SQL节点信息
MappedStatement ms = sqlSession.getConfig().getMappedStatement(statementId);
if (ms == null) {
throw new RuntimeException("无对应的SQL, id:" + statementId);
}
String type = ms.getStatementType();
Object param = (args != null) ? args[0] : null;
// 根据SQL类型执行对应的数据库操做方法
if ("insert".equals(type)) {
return sqlSession.insert(statementId, param);
} else if ("update".equals(type)) {
return sqlSession.update(statementId, param);
} else if ("delete".equals(type)) {
return sqlSession.delete(statementId, param);
} else if ("select".equals(type)) {
return sqlSession.selectList(statementId, param);
}
return null;
}
}
复制代码
测试bash
public static void main(String[] args) {
// 建立SQL会话工厂
SqlSessionFactory sf = new SqlSessionFactoryBean("*_mapper.xml").build();
MapperFactory factory = new MapperFactory(sf);
// 经过工厂类获取DAO
UserDAO userDAO = factory.getMapper(UserDAO.class);
// 调用DAO中方法
int count = userDAO.insertUser(new User(1L, "zhangsan", 20, "sssss", "ok"));
List<User> userList = userDAO.selectUser();
// 输出查询结果
System.out.println(count);
for (User u : userList) {
System.out.println("| " + u.getId() + " | " + u.getUname() + " | ");
}
}
复制代码