mybatis-interceptor

栏目: Java · 发布时间: 5年前

package bj.mybatisinterceptor;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.LoggerFactory;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import javax.validation.constraints.NotNull;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Created by BaiJiFeiLong@gmail.com at 2018/12/26 下午1:20
 */
@SpringBootApplication
public class App implements ApplicationListener<ApplicationReadyEvent> {

    public static void main(String[] args) {
        new SpringApplicationBuilder(App.class).web(WebApplicationType.NONE).run(args);
    }

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private UserMapper userMapper;

    @Override
    public void onApplicationEvent(@NotNull ApplicationReadyEvent event) {
        ((Logger) LoggerFactory.getLogger(App.class.getPackage().getName())).setLevel(Level.INFO);

        jdbcTemplate.execute("DROP TABLE IF EXISTS user");
        jdbcTemplate.execute("CREATE TABLE user(id INT PRIMARY KEY AUTO_INCREMENT, username TEXT)");
        jdbcTemplate.execute("INSERT INTO user(username) VALUES ('alpha'), ('beta')");

        System.out.println("findAll:");
        System.out.println(userMapper.findAll());
        System.out.println();

        System.out.println("findAllLimitOneByAnnotation:");
        System.out.println(userMapper.findAllLimitOneByAnnotation());
        System.out.println();

        System.out.println("findAll again:");
        System.out.println(userMapper.findAll());
        System.out.println();

        System.out.println("findAllLimitOneByAnnotation again:");
        System.out.println(userMapper.findAllLimitOneByAnnotation());
        System.out.println();
    }

    @Bean
    public DataSource dataSource() {
        return new HikariDataSource() {{
            setJdbcUrl("jdbc:mysql://localhost/foo");
            setUsername("root");
            setPassword("root");
        }};
    }

    @Mapper
    @Component
    interface UserMapper {
        @Select("SELECT * FROM user")
        List<Map<String, Object>> findAll();

        @LimitOne
        @Select("SELECT * FROM user")
        List<Map<String, Object>> findAllLimitOneByAnnotation();
    }


    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface LimitOne {
    }

    @Component
    @Aspect
    static class MyAspect {
        @Around("@annotation(limitOne)")
        public Object doAnnotation(ProceedingJoinPoint joinPoint, LimitOne limitOne) {
            try {
                LimitOneMyBatisInterceptor.LIMIT_ONE.set(Object.class);
                return joinPoint.proceed();
            } catch (Throwable throwable) {
                throw new RuntimeException(throwable);
            } finally {
                LimitOneMyBatisInterceptor.LIMIT_ONE.remove();
            }
        }
    }

    @Component
    @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
    static class LimitOneMyBatisInterceptor implements Interceptor {

        final static ThreadLocal<Object> LIMIT_ONE = new ThreadLocal<>();

        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            final String SQL = "delegate.boundSql.sql";
            MetaObject metaObject = SystemMetaObject.forObject(invocation.getTarget());
            if (LIMIT_ONE.get() != null)
                metaObject.setValue(SQL, String.format("%s LIMIT 1", metaObject.getValue(SQL)));
            System.out.printf("SQL: \033[1;35m%s\033[0m\n", metaObject.getValue(SQL));
            return invocation.proceed();
        }

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

        @Override
        public void setProperties(Properties properties) {
        }
    }
}

控制台输出

findAll:
SQL: SELECT * FROM user
[{id=1, username=alpha}, {id=2, username=beta}]

findAllLimitOneByAnnotation:
SQL: SELECT * FROM user LIMIT 1
[{id=1, username=alpha}]

findAll again:
SQL: SELECT * FROM user
[{id=1, username=alpha}, {id=2, username=beta}]

findAllLimitOneByAnnotation again:
SQL: SELECT * FROM user LIMIT 1
[{id=1, username=alpha}]

以上所述就是小编给大家介绍的《mybatis-interceptor》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C程序设计

C程序设计

谭浩强 / 清华大学出版社 / 2005-7-1 / 26.00元

《C程序设计(第3版)》作者具有丰富的教学经验和编写教材的经验,并针对初学者的特点,精心策划、准确定位,使得《C程序设计(第3版)》概念清晰、例题丰富、深入浅出,受到专家和读者的一致好评。《C程序设计(第3版)》被普遍认为是学习C语言的好教材,并被全国大多数高校选用。十多年来《C程序设计(第3版)》累计发行了800多万册,刨同类书的全国最高记录,是学习C语言的主流用书。《C程序设计(第3版)》曾荣......一起来看看 《C程序设计》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具