三月份的时候来到一家新公司,熟悉项目代码时发现数据库操作都是原生JDBC,由于数据库表字段数量庞大,再加上sql拼接,看的我头大,于是我便打算将MyBatisPlus整合进去,中间踩了不少坑,不过用了一段时间还挺成功,不再多说,上代码
0、思路
mybatisplus的源码我看过几遍,与mybatis类似只是重写了一些类,其中的核心还是SqlSession,SqlSession是由SqlSessionFactory工厂创建,SqlSessionFactory是由SqlSessionFactoryBuilder构造的,builder在构造会话工厂时需要configuration配置信息,在spring项目中使用的是mapper.xml配置文件来加载配置信息,这里使用纯代码进行配置
1、构建SqlSessionFactory
LogFactory.useStdOutLogging(); 这个一定要加上!!!
这个地方很坑,如果只在configuration中配置了日志,在实际执行时不会打印sql,一定要加上
private static SqlSessionFactory sqlSessionFactory;
static {
try {
LogFactory.useStdOutLogging();
sqlSessionFactory = initSqlSessionFactory();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
创建environment和configuration对象
MyBatisPlus对configuration、sqlSessionFactoryBuilder、interceptor等类进行了重写
private static SqlSessionFactory initSqlSessionFactory() throws Exception {
Environment environment = new Environment("development",//id自定义
new JdbcTransactionFactory(), //事务处理工厂
initDataSource());//数据源
MybatisConfiguration configuration = new MybatisConfiguration(environment);//mybatis配置
configuration.setCacheEnabled(true);//开启二级缓存
configuration.addMappers("com.demo.mapper");//mapper接口位置
configuration.setLogImpl(StdOutImpl.class);//日志
configuration.setMapUnderscoreToCamelCase(true);//驼峰
configuration.setUseGeneratedKeys(true);//主键回填
configuration.addInterceptor(initPageInterceptor());//分页
return new MybatisSqlSessionFactoryBuilder().build(configuration);
}
加载数据源initDataSource()(我使用的是oracle数据库)
private static DataSource initDataSource() throws Exception {
OracleDataSource dataSource = new OracleDataSource();
dataSource.setURL("url");
dataSource.setUser("user");
dataSource.setPassword("password");
//这里只做了最简单的配置,还有其他选项可以自行选择
return dataSource;
}
自定义拦截器initPageInterceptor()
private static Interceptor initPageInterceptor() {
//创建mybatis-plus插件对象
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//构建分页插件
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setDbType(DbType.ORACLE);
paginationInnerInterceptor.setOverflow(true);
paginationInnerInterceptor.setMaxLimit(500L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();//动态修改表名
dynamicTableNameInnerInterceptor.setTableNameHandler(
new MyTableNameHandler("STUDENT_T")
);
interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
return interceptor;
}
MyBatis原生的分页是查询所有记录然后在内存中分页,拦截器会拦截sql进行修改实现分页
动态修改表名拦截器则是在数据库分表时才会使用,可以避免相同表结构的重复编码
2、创建SqlSession对象
autoCommit
是否自动提交事务
execType
执行器类型:simple、reuse、batch(批量)
public static SqlSession openSession(ExecutorType execType, boolean autoCommit) {
SqlSession sqlSession;
int count = 0;
do {
try {
if (execType == null) {
sqlSession = sqlSessionFactory.openSession(autoCommit);
} else {
sqlSession = sqlSessionFactory.openSession(execType, autoCommit);
}
if (sqlSession != null) {
break;
}
TimeUnit.SECONDS.sleep(60 * Math.round((Math.random() * 2) + 1));
if (++count >= 10) {
break;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} while (true);
if (count == 10) {
System.out.println("获取数据库会话超时");
}
return sqlSession;
}
3、获取mapper对象
实体类与接口以及xml都通过MyBatisX生成
实体类
如果实体类中使用的是复合主键,可以添加mybatisplus-plus的jar包并配合一些注解实现复合主键
@TableName(value = "STUDENT")
@Data
@NoArgsConstructor
public class Student implements Serializable {
/**
* 唯一标识
*/
@TableId(value = "S_Id")
private String sId;
/**
* 姓名
*/
@TableField(value = "NAME")
private String name;
}
mapper接口
public interface StudentMapper extends BaseMapper<Student> {
}
获取Mapper对象
SqlSession sqlSession = MyBatisUtils.openSession(null,true);
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
获取完mapper对象之后就可以很方便使用baseMapper中自定义的一些方法啦
最后
我们的项目并没有使用maven或gradle,而是直接导入的jar包
使用过程中可能会报一些缺少jar包的错误(缺少spring框架的一些资源),由于时间太久我之前也没记录这些错误,所以如果出现这类错误可以直接问度娘看看缺少哪些jar包,下载下来添加即可
有不严谨的地方欢迎大家指正