7
回答
spring+mybatis的实体bean,加默认值系统时间
极速云服务器,低至1.04元/天>>>   

我有几个字段,创建人,创建时间,修改人,修改时间,可以在bean上加注解,自动获取系统时间和当前登录人么?因为每次操作的时候都需要手动调setter方法去设,功能模块多就比较麻烦。

/**
 * 创建人
 */
@TableField(value = "CREATE_BY")
private String createBy;

/**
 * 创建人名称
 */
@TableField(value = "CREATE_NAME")
private String createName;

/**
 * 创建时间
 */
@TableField(value = "CREATE_TIME")
private String createTime;
举报
顺其自然001
发帖于6个月前 7回/251阅

mybatisplus 有填充公共字段的做法。

如果不用mybatispuls,直接使用mybatis的拦截器就可以了。

在mybatis的配置文件中增加

    <plugins>
        <plugin interceptor="group.raber.saber.mybatis.interceptor.WhenDidInterceptor" />
    </plugins>

拦截器实现代码:

package group.raber.saber.mybatis.interceptor;

import group.raber.saber.kit.BeanKit;
import group.raber.saber.kit.DateKit;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.util.Properties;
import java.util.regex.Pattern;

/**
 * mybatis日期处理拦截
 */
//method只定义了update,query,flushStatements,commit,rollback,createCacheKey,isCached,clearLocalCache,deferLoad,getTransaction,close,isClosed这几个方法
@Intercepts({
        @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class,RowBounds.class, ResultHandler.class }),
        @Signature(method = "update",type = Executor.class,  args = {MappedStatement.class, Object.class }),
//        @Signature(method = "prepare", type = StatementHandler.class, args = { Connection.class })
})
public class WhenDidInterceptor implements Interceptor {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    private Properties properties;

    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object beanObject = args[1];

        String sqlId = mappedStatement.getId();
        logger.trace("mybatis-sqlId:"+sqlId);
        Object target = invocation.getTarget();

        Configuration configuration = mappedStatement.getConfiguration();
        StatementHandler handler = configuration.newStatementHandler((Executor) target, mappedStatement,beanObject, RowBounds.DEFAULT, null, null);
        String methodName = invocation.getMethod().getName();

        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql();

        //insert,update,delete均为update
        if("update".equals(methodName)){
            if(isInsert(sql)){
                if(BeanKit.propertyExists(beanObject,"createdTime"))BeanKit.setProperty(beanObject, "createdTime", DateKit.now());
                if(BeanKit.propertyExists(beanObject,"updatedTime"))BeanKit.setProperty(beanObject, "updatedTime", DateKit.now());
            }else if(isUpdate(sql)){
                if(BeanKit.propertyExists(beanObject,"updatedTime"))BeanKit.setProperty(beanObject, "updatedTime", DateKit.now());
            }
        }

        return invocation.proceed();
    }


    Pattern insertPattern = Pattern.compile("\\s*insert",Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
    protected boolean isInsert(String sql){
        return insertPattern.matcher(sql).find();
    }
    Pattern updatePattern = Pattern.compile("\\s*update",Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
    protected boolean isUpdate(String sql){
        return updatePattern.matcher(sql).find();
    }

    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}

系统时间好处理,取当前登录用户麻烦一点点。

因为拦截器环境下,“没有办法”拿到web环境中的session对象。这个时候,可以使用ThreadLocal,把当前登录的用户绑定到当前线程上,然后在这个拦截器中直接取出后,设置进去就可以了。

这个需求,在管理信息系统(MIS)以及其他作业系统中,会经常有这需求。

--- 共有 1 条评论 ---
顺其自然001mybatis plus怎么做?有范例么? 6个月前 回复

引用来自“田舍先生”的评论

mybatisplus 有填充公共字段的做法。

如果不用mybatispuls,直接使用mybatis的拦截器就可以了。

在mybatis的配置文件中增加

    <plugins>
        <plugin interceptor="group.raber.saber.mybatis.interceptor.WhenDidInterceptor" />
    </plugins>

拦截器实现代码:

package group.raber.saber.mybatis.interceptor;

import group.raber.saber.kit.BeanKit;
import group.raber.saber.kit.DateKit;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.util.Properties;
import java.util.regex.Pattern;

/**
 * mybatis日期处理拦截
 */
//method只定义了update,query,flushStatements,commit,rollback,createCacheKey,isCached,clearLocalCache,deferLoad,getTransaction,close,isClosed这几个方法
@Intercepts({
        @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class,RowBounds.class, ResultHandler.class }),
        @Signature(method = "update",type = Executor.class,  args = {MappedStatement.class, Object.class }),
//        @Signature(method = "prepare", type = StatementHandler.class, args = { Connection.class })
})
public class WhenDidInterceptor implements Interceptor {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    private Properties properties;

    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object beanObject = args[1];

        String sqlId = mappedStatement.getId();
        logger.trace("mybatis-sqlId:"+sqlId);
        Object target = invocation.getTarget();

        Configuration configuration = mappedStatement.getConfiguration();
        StatementHandler handler = configuration.newStatementHandler((Executor) target, mappedStatement,beanObject, RowBounds.DEFAULT, null, null);
        String methodName = invocation.getMethod().getName();

        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql();

        //insert,update,delete均为update
        if("update".equals(methodName)){
            if(isInsert(sql)){
                if(BeanKit.propertyExists(beanObject,"createdTime"))BeanKit.setProperty(beanObject, "createdTime", DateKit.now());
                if(BeanKit.propertyExists(beanObject,"updatedTime"))BeanKit.setProperty(beanObject, "updatedTime", DateKit.now());
            }else if(isUpdate(sql)){
                if(BeanKit.propertyExists(beanObject,"updatedTime"))BeanKit.setProperty(beanObject, "updatedTime", DateKit.now());
            }
        }

        return invocation.proceed();
    }


    Pattern insertPattern = Pattern.compile("\\s*insert",Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
    protected boolean isInsert(String sql){
        return insertPattern.matcher(sql).find();
    }
    Pattern updatePattern = Pattern.compile("\\s*update",Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
    protected boolean isUpdate(String sql){
        return updatePattern.matcher(sql).find();
    }

    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}

系统时间好处理,取当前登录用户麻烦一点点。

因为拦截器环境下,“没有办法”拿到web环境中的session对象。这个时候,可以使用ThreadLocal,把当前登录的用户绑定到当前线程上,然后在这个拦截器中直接取出后,设置进去就可以了。

这个需求,在管理信息系统(MIS)以及其他作业系统中,会经常有这需求。

你去看看他的官方文档

引用来自“顺其自然001”的评论

@田舍先生 

请问,这两个要引入什么包?

import group.raber.saber.kit.BeanKit;
import group.raber.saber.kit.DateKit;

 

唉,后面你提的其他问题,我不想再回答了。你太懒了,还不思考。

这是我的代码,无非就是告诉你,他是一个取系统时间的功能实现。

这代码,你拿去去是用不起来的。

自己把意思看明白后,按这个思路,自撸一个吧。

--- 共有 4 条评论 ---
顺其自然001 回复 @田舍先生 : 多谢了 6个月前 回复
Rober萝卜 回复 @顺其自然001 : 那,你就用mybatis原生的拦截器吧。我一直使用的这个。上面那个DateKit是我的类,DateKit.now()无非等于new Date(),至于取当前用户,你要是用过ThreadLocal,知道怎么把当前登录的用户绑定到线程上,那这个问题就完全解决了 6个月前 回复
顺其自然001不知道是不是和mybatis版本有关系. 6个月前 回复
顺其自然001我项目用了mybatisplus,所以直接使用了他提供的填充方法, 发现根本没有效果,debug发现,值可以填充到bean里面,但是,在填充bean之前,就已经根据未填充前的bean生成了sql,sql中并不包含自动填充的属性,所以bean里面有值也无法更新到数据库,升级到了最新版本也不行. 6个月前 回复

我有个疑问,在运行到下面一行代码的时候,这个update的sql语句实际已经生成了,

我在bean里增加属性,会改变这个sql吗?我用mybatisplus也是遇到这样的问题,属性是放进去了

可以是sql还是原来的那个,在set后面并没有增加我已经赋值的那几个公共字段.属性的赋值都是没有问题,用户名和日期都正确,就是不进入最终执行的sql,难道还遗漏了哪里?

 

String sql = boundSql.getSql();
顶部