JFinal集成MybatisPlus

背景:最近接手了一个新项目,但是领导要求使用jplus,而一起做这个项目的同学表示没有orm框架太过折磨,并且之前并没有使用过JFinal(当然我也没用过ヽ(ー_ー)ノ),于是一合计干脆把mybatisPlus搞进来。

翻阅Jplus官方文档可以看到 在JFinal项目初始化后会调用 IBoot4jAppListenerBase 类的 onStart 方法,给于开发者在项目启动后加入一些自定的初始化逻辑,我们可以在这里配置MybatisPlus初始化方法

public class WebInitializer extends IBoot4jAppListenerBase {
    public final static Prop prop = PropKit.use("application.properties");
	@Override
	public void onStart(){
        MybatisPlusConfig.initSqlSession(
            // 替换为自己的Mapper路径
            prop.get("mybatis.path","cn.iboot4j.admin.mapper")
        );
	}
}

以下是MybatisPlus初始化方法,嫌麻烦可以直接复制(^_−)☆

public class MybatisPlusConfig {
    static String url = IBoot4j.configValue("datasource.url");
    static String user = IBoot4j.configValue("datasource.user");
    static String password = IBoot4j.configValue("datasource.password");
    @Getter
    private static SqlSessionFactory sqlSessionFactory;

    public static void initSqlSession(String mapperPath){
        //设置数据源
        Environment environment = new Environment("1", new JdbcTransactionFactory(), initDataSource());
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //这是mybatis-plus的配置对象,对mybatis的Configuration进行增强
        MybatisConfiguration configuration = new MybatisConfiguration();
        //这是初始化配置,后面会添加这部分代码
        initConfiguration(configuration);
        //这是初始化连接器,如mybatis-plus的分页插件
        configuration.addInterceptor(initInterceptor());
        //扫描mapper接口所在包
        configuration.addMappers(mapperPath);
        //配置日志实现
        configuration.setLogImpl(StdOutImpl.class);
        configuration.setDefaultEnumTypeHandler(org.apache.ibatis.type.EnumOrdinalTypeHandler.class);
        //configuration.addInterceptor(new SqlLogInterceptor());
        //构建mybatis-plus需要的globalconfig
        GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
        //此参数会自动生成实现baseMapper的基础方法映射
        globalConfig.setSqlInjector(new DefaultSqlInjector());
        //设置数据生成
        globalConfig.setMetaObjectHandler(new MybatisPlusMetaObjectHandler());
        //雪花id
        globalConfig.getDbConfig().setIdType(IdType.ASSIGN_ID);
        globalConfig.getDbConfig().setTableUnderline(true);
        globalConfig.getDbConfig().setLogicDeleteField("is_deleted");
        globalConfig.getDbConfig().setLogicDeleteValue("1");
        globalConfig.getDbConfig().setLogicNotDeleteValue("0");
        //设置id生成器
        globalConfig.setIdentifierGenerator(new DefaultIdentifierGenerator());
        //设置超类mapper
        globalConfig.setSuperMapperClass(BaseMapper.class);
        configuration.setEnvironment(environment);
        //构建sqlSessionFactory
        sqlSessionFactory = builder.build(configuration);
    }
    private static DataSource initDataSource() {
        MysqlDataSource dataSource = new MysqlDataSource();
        dataSource.setURL(url);
        dataSource.setUser(user);
        dataSource.setPassword(password);
        if (StringUtils.isBlank(dataSource.getURL())){
            dataSource.setURL("数据库连接");
            dataSource.setUser("user");
            dataSource.setPassword("pwd");
        }
        return dataSource;
    }
    /**
     * 初始化配置
     *
     * @param configuration
     */
    private static void initConfiguration(MybatisConfiguration configuration) {
        //开启驼峰大小写转换
        configuration.setMapUnderscoreToCamelCase(true);
        //配置添加数据自动返回数据主键
        configuration.setUseGeneratedKeys(true);
    }
    private static Interceptor initInterceptor() {
        //创建mybatis-plus插件对象
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //构建分页插件
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        paginationInnerInterceptor.setOverflow(true);
        paginationInnerInterceptor.setMaxLimit(500L);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }
}
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
    private static final String CREATE_TIME = "createTime";

    private static final String UPDATE_TIME = "updateTime";

    private static final String ID_DELETED = "isDeleted";
    @Override
    public void insertFill(MetaObject metaObject) {
        if (metaObject.hasSetter(CREATE_TIME)) {
            this.fillStrategy(metaObject, CREATE_TIME, LocalDateTime.now());
        }
        if (metaObject.hasSetter(UPDATE_TIME)) {
            this.fillStrategy(metaObject, UPDATE_TIME, LocalDateTime.now());
        }
        if (metaObject.hasSetter(ID_DELETED)) {
            this.fillStrategy(metaObject, ID_DELETED, 0);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        if (metaObject.hasSetter(UPDATE_TIME)) {
            this.strictUpdateFill(metaObject, UPDATE_TIME, LocalDateTime.class, LocalDateTime.now());
        }
    }
}

 在spring中原来的使用方法是将mapper注入IOC后进行使用,但是因为JFinal官方并没有集成orm框架文档(也可能我没看到( ̄ェ ̄;)),我并不确定以后升级框架会不会导致IOC注入mybatis相关的代码失效,所以从解耦提升稳定性方面考虑,就不使用Jplus框架带的IOC了,我们这里手动创建数据库会话进行操作

public class Mybatis {
    private static final Map<Class<?>,SqlSession> SQL_SESSION_MAP = new ConcurrentHashMap<>();
    /**
     * @param clazz:
     * @return T
     * @author luoliang
     * @description 自动提交
     * @date 2024/4/19 9:28
     */
    public static <T extends BaseMapper<?>> T getMapper(Class<T> clazz){
        return getMapper(clazz,true);
    }

    public static <T extends BaseMapper<?>> T getMapper(Class<T> clazz,Boolean autoCommit) {
        SqlSession sqlSession = MybatisPlusConfig.getSqlSessionFactory().openSession(autoCommit);
        SQL_SESSION_MAP.put(clazz,sqlSession);
        return sqlSession.getMapper(clazz);
    }

    @Synchronized
    public static void close(Class<?> clazz){
        SqlSession sqlSessionClose = SQL_SESSION_MAP.get(clazz);
        if (sqlSessionClose!=null){
            sqlSessionClose.commit();
            sqlSessionClose.close();
            SQL_SESSION_MAP.remove(clazz);
        }
    }
}

这里就集成完毕了,下面是使用方式

1.像往常使用mybatisPlus一样 定义好Mapper类

2.使用mybatisPlus并关闭会话,到这里就完成啦( ̄▽ ̄)~*

后续有同学提出,啊~ 还要手动关闭会话,能不能再简单一点呢?

可以。我们可以使用aop进行自动的会话管理

/**
 * @author luoliang
 * @description aop自动提交 使用示例见UserServiceImpl
 *  jfinal没办法对接口使用aop 可能在代码中会存在需要手动提交会话和释放会话的地方
 *  比如在 UserServiceImpl中使用了非UserMapper的会话 当出现这种情况 为了保险起见请手动释放sqlSession
 */
@Slf4j
public class SqlSessionInterceptor implements Interceptor {
    @Override
    public void intercept(Invocation invocation) {
        invocation.invoke();
        String convertedClassName = convertToMapperClassName(invocation.getTarget().toString());
        try {
            Mybatis.close(Class.forName(convertedClassName));
        } catch (ClassNotFoundException e) {
            log.error("SqlSessionInterceptorError : "+convertedClassName);
        }
    }
    public static String convertToMapperClassName(String originalClassName) {
        int implIndex = originalClassName.indexOf("impl.");
        if (implIndex != -1) {
            int serviceImplIndex = originalClassName.indexOf("ServiceImpl", implIndex + 5);
            if (serviceImplIndex != -1) {
                // 替换为自己的Mapper路径
                return "cn.iboot4j.admin.mapper." + originalClassName.substring(implIndex + 5, serviceImplIndex) + "Mapper";
            }
        }
        return null;
    }
}

然后在需要使用mybatisPlus的地方加上aop即可 

但是这里请注意,JFinal的AOP与Spring中的AOP不同,Jplus更像是一种请求拦截,用于对请求前后进行增强,所以这里会存在一点点隐患,例如在 UserServiceImpl中使用了非UserMapper的会话 会导致非UserMapper的会话无法关闭,所以 为了保险起见还是请手动释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值