1. 借助javassist编写GenerateDaoProxy类
package com.sndu.bank.utils;
import org.apache.ibatis.javassist.CannotCompileException;
import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtMethod;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.SqlSession;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* 工具类 生成Dao实现类(动态生成Dao代理类)
*/
public class GenerateDaoProxy {
public static Object generate(SqlSession sqlSession, Class daoInterface){
//类池
ClassPool pool = ClassPool.getDefault();
//制造类
final CtClass ctClass = pool.makeClass(daoInterface.getName() + "Proxy");//实际本质就是在内存中动态生成一个代理类
//制造接口
CtClass ctInterface = pool.makeInterface(daoInterface.getName());
//实现接口
ctClass.addInterface(ctInterface);
//实现接口中所有方法
Method[] methods = daoInterface.getDeclaredMethods();
Arrays.stream(methods).forEach(method -> {
//method是抽象方法
//将method这个抽象方法实现
try {
StringBuilder methodCode = new StringBuilder();
methodCode.append("public ");
methodCode.append(method.getReturnType().getName());
methodCode.append(" ");
methodCode.append(method.getName());
methodCode.append("(");
Class<?>[] parameterTypes = method.getParameterTypes();
for(int i = 0; i < parameterTypes.length; i++){
Class<?> parameterType = parameterTypes[i];
methodCode.append(parameterType.getName());
methodCode.append(" ");
methodCode.append("arg" + i);
if(i != parameterTypes.length - 1){
methodCode.append(",");
}
}
methodCode.append(")");
methodCode.append("{");
methodCode.append("org.apache.ibatis.session.SqlSession sqlSession = com.sndu.bank.utils.SqlSessionUtil.openSession();");
//需要知道是什么类型的sql
//namespace必须是dao接口中的全限定名称,id必须是dao中的接口名
String sqlId = daoInterface.getName() + "." + method.getName();
SqlCommandType sqlCommandType = sqlSession.getConfiguration().getMappedStatement(sqlId).getSqlCommandType();
if(sqlCommandType == SqlCommandType.INSERT){
}
if(sqlCommandType == SqlCommandType.DELETE){
}
if(sqlCommandType == SqlCommandType.UPDATE){
methodCode.append("return sqlSession.update(\""+sqlId+"\", arg0);");
}
if(sqlCommandType == SqlCommandType.SELECT){
String returnType = method.getReturnType().getName();
methodCode.append("return ("+returnType+")sqlSession.selectOne(\""+sqlId+"\", arg0);");
}
methodCode.append("}");
CtMethod ctMethod = CtMethod.make(methodCode.toString(), ctClass);
ctClass.addMethod(ctMethod);
} catch (Exception e) {
e.printStackTrace();
}
});
//创建对象
Object obj = null;
try {
Class<?> clazz = ctClass.toClass();
obj = clazz.newInstance();
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return obj;
}
}
后续我们只需要写接口即可,不用写实现类。
2.使用MyBatis内置的代理功能
MyBatis内置了代理模式。在内存中生成Dao接口的代理类,然后生成代理类的实例。MyBatis能使用这种代理功能的前提是XxxxxMapper.xml中的namespace使用全限定名称,id使用类名。
代码:
private AccountDao accountDao = SqlSessionUtil.openSession().getMapper(AccountDao.class);
3.面向接口编写CRUD
CarMapper
package com.sdnu.mybatis.mapper;
import com.sdnu.mybatis.pojo.Car;
import java.util.List;
public interface CarMapper {
/**
* 增
* @param car 汽车
* @return
*/
int insert (Car car);
/**
* 根据Id删除Car
* @return
*/
int deleteById(Long id);
/**
* 更新
* @param car
* @return
*/
int update(Car car);
/**
* 根据id查询汽车信息
* @param id
* @return
*/
Car selectById(Long id);
/**
* 查询所有汽车信息
* @return
*/
List<Car> selectAll();
}
CarMapperTest
package com.sdnu.mybatis.test;
import com.sdnu.mybatis.mapper.CarMapper;
import com.sdnu.mybatis.pojo.Car;
import com.sdnu.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class CarMapperTest {
@Test
public void testInsert(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(null, "8888", "劳斯莱斯", 188.0, "2023-03-27", "燃油车");
int count = mapper.insert(car);
System.out.println(count);
sqlSession.commit();
};
@Test
public void testDeleteById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
int count = mapper.deleteById(30L);
System.out.println(count);
sqlSession.commit();
};
@Test
public void testUpdate(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(29L, "989999998", "奔驰C", 9898.0, "2023-03-27", "燃油车");
int count = mapper.update(car);
System.out.println(count);
sqlSession.commit();
}
@Test
public void testSelectById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = mapper.selectById(28L);
System.out.println(car);
}
@Test
public void testSelectAll(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> list = mapper.selectAll();
for(Car obj : list){
System.out.println(obj);
}
}
}