JFinal

登录 注册

jfinal 集成 mybatis,支持事务

jfinal集成mybatis, 还未完善,仅供参考!后续还得写一个hanlder来处理连接关闭。

一、mybatis配置文件

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- config params as the following -->
        <property name="supportMethodsArguments" value="true"/>
    </plugin>
</plugins>
<environments default="development">
    <environment id="development">
        <transactionManager type="com.sl.basic.common.MyJdbcTransactionFactory" />
        <!-- 配置数据库连接信息 -->
        <dataSource type="com.sl.db.DruidMybatis">
            <!--注意这里的 name与environment的id保持一致 -->
            <property name="name" value="development" />
            <property name="url" value="jdbc:mysql://localhost:3306/demo" />
            <property name="username" value="root" />
            <property name="password" value="mysql" />
        </dataSource>
    </environment>
    <environment id="development1111">
        <transactionManager type="com.sl.basic.common.MyJdbcTransactionFactory" />
        <!-- 配置数据库连接信息 -->
        <dataSource type="com.sl.db.DruidMybatis">
            <property name="url" value="jdbc:mysql://localhost:3306/demo1" />
            <property name="username" value="root" />
            <property name="name" value="development1111" />
            <property name="password" value="mysql" />
        </dataSource>
    </environment>
</environments>

二、数据源配置

package com.sl.db;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;

public class DruidMybatis extends UnpooledDataSourceFactory {
    public DruidMybatis() {
        this.dataSource = new DruidDataSource();
    }
}
package com.sl.basic.common;

import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Properties;

public class MyJdbcTransactionFactory implements TransactionFactory {
    public MyJdbcTransactionFactory() {
    }

    public void setProperties(Properties props) {
    }

    public Transaction newTransaction(Connection conn) {
        return new MyJdbcTransaction(conn);
    }

    public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
        return new MyJdbcTransaction(ds, level, autoCommit);
    }
}

package com.sl.basic.common;

import com.alibaba.druid.pool.DruidDataSource;
import com.jfinal.plugin.activerecord.Config;
import com.jfinal.plugin.activerecord.DbKit;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.jdbc.JdbcTransaction;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class MyJdbcTransaction extends JdbcTransaction implements Transaction {
    public MyJdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
        super(ds, desiredLevel, desiredAutoCommit);
    }

    public MyJdbcTransaction(Connection connection) {
        super(connection);
    }

    @Override
    public Connection getConnection() throws SQLException {
        //从DbKit中获取连接
        Connection connection = getConfig().getConnection();
        this.connection = connection;
        return connection;
    }

    protected Config getConfig() {
        String configName = ((DruidDataSource) dataSource).getName();
        return DbKit.getConfig(configName);
    }

    @Override
    public void close() throws SQLException {
        System.out.println("================释放jdbc连接=====================");
        getConfig().close(getConnection());
    }
}

package com.sl.basic.common;

import com.jfinal.plugin.activerecord.DbKit;
import com.sl.kit.StrKit;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Config;
import tk.mybatis.mapper.mapperhelper.MapperHelper;

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;


public class MybatisHelper {
    private static final Map<String,SqlSessionFactory> sessionFactoryMap = new HashMap<>();

    public static SqlSessionFactory getSqlSessionFactory() {
        return getSqlSessionFactory(null);
    }

    public static SqlSessionFactory getSqlSessionFactory(String environment) {
        
        SqlSessionFactory sessionFactory = sessionFactoryMap.get(StrKit.defaultIfEmpty(environment,"default"));
        if(sessionFactory!=null)return sessionFactory;
        Reader reader = null;
        try {
            reader = Resources.getResourceAsReader("conf.xml");
            sessionFactory = new SqlSessionFactoryBuilder().build(reader,environment);

            sessionFactoryMap.put(StrKit.defaultIfEmpty(environment,"default"),sessionFactory);
            
            //创建一个MapperHelper
            MapperHelper mapperHelper = new MapperHelper();
            //特殊配置
            Config config = new Config();
            // 设置UUID生成策略
            // 配置UUID生成策略需要使用OGNL表达式
            // 默认值32位长度:@java.util.UUID@randomUUID().toString().replace("-", "")
            //config.setUUID("");
            // 主键自增回写方法,默认值MYSQL,详细说明请看文档
//            config.setIDENTITY("HSQLDB");
            // 支持方法上的注解
            // 3.3.1版本增加
            config.setEnableMethodAnnotation(true);
            config.setNotEmpty(true);
            //校验Example中的类型是否一致
            config.setCheckExampleEntityClass(true);
            //启用简单类型
            config.setUseSimpleType(true);
            // 序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle
            // 可选参数一共3个,对应0,1,2,分别为SequenceName,ColumnName, PropertyName
            //config.setSeqFormat("NEXT VALUE FOR {0}");
            // 设置全局的catalog,默认为空,如果设置了值,操作表时的sql会是catalog.tablename
            //config.setCatalog("");
            // 设置全局的schema,默认为空,如果设置了值,操作表时的sql会是schema.tablename
            // 如果同时设置了catalog,优先使用catalog.tablename
            //config.setSchema("");
            // 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)
            //config.setOrder("AFTER");
            //设置配置
            mapperHelper.setConfig(config);
            // 注册通用Mapper接口 - 可以自动注册继承的接口
            mapperHelper.registerMapper(Mapper.class);
//            mapperHelper.registerMapper(MySqlMapper.class);
//            mapperHelper.registerMapper(SqlServerMapper.class);
//            mapperHelper.registerMapper(IdsMapper.class);
            //配置完成后,执行下面的操作
            Configuration configuration = sessionFactory.getConfiguration();
            mapperHelper.processConfiguration(configuration);

            //事务支持,如下代码
            com.jfinal.plugin.activerecord.Config conf = new com.jfinal.plugin.activerecord.Config(configuration.getEnvironment().getId(),configuration.getEnvironment().getDataSource());
            DbKit.addConfig(conf);
            return sessionFactory;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if(reader!=null)reader.close();
            } catch (IOException e) {
                System.err.println("流关闭错误:" + e.getMessage());
            }
        }
    }

    /**
     * 获取Session
     *
     * @return
     */
    public static SqlSession getSqlSession() {
        return getSqlSessionFactory().openSession();
    }

    public static SqlSession getSqlSession(String environment){
        return getSqlSessionFactory(environment).openSession();
    }
}

如何启用事务?

和jfinal activerecord事务一模一样,在对应的方法加 @Before(Tx.class)

评论

  • 09-04 11:06
    牛逼了,居然还还整合mybatis,你这个整合没意义啊,jfinal的数据库本身就已经很好用了,为什么还要整合mybatis,
  • 09-04 11:40
    @穿越123 并没有说jfinal的activerecord不好用,因为我没用过mybatis,尝试着先了解一下,没有对比,仅供需要的人参考
  • 09-04 11:43
    @穿越123 贴出来的代码都很简陋,没做任何封装,单纯的实现,暂时没打算进一步研究了
  • 09-04 11:44
    @冰 用过以后,反馈一下使用的对比,尤其是生成 sql 管理功能,这个用户体验应该是完全不同的
  • 09-04 11:58
    @JFinal 暂时不会用了,实际项目中用的activerecord,感觉model与dao绑的太死,以及不支持一级缓存的原因,才有了了解mybatis的想法
  • 09-04 12:24
    @JFinal 波总下版本可以考虑考虑一级缓存,这块感觉是硬性需求呀
  • 09-04 12:29
    @JFinal 还有控制器正则匹配功能,shiro给url授权,常规的url并不能满足需要,如单位管理/basic/orgmng/:orgId, 对于:orgId会具体指向某个单位,我会给如/basic/orgmng/1授权有管理权限,这个我在自己的项目中修改源代码实现的
  • 09-04 12:38
    @冰 缓存搞得耦合度太高,可能会有很大副作用,而且缓存可以在业务层这种更高层面做,效果可能更好
  • 09-04 16:14
    @冰 你那个代码发帖是怎么编辑的呀,我怎么弄不来呢
  • 09-05 11:51
    @穿越123 选择 代码语言->java ,粘贴你的代码
  • 发送