Spring Boot MyBatis 通用Mapper插件集成

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

看本文之前,请确保你已经在SpringBoot中集成MyBatis,并能正常使用。
如果没有,那么请先移步 http://blog.csdn.net/catoop/article/details/50553714 做了解后,再按本文步骤操作。

使用MyBatis在我们通过xml集中配置SQL,并通过创建接口Mapper文件来完成持久化DAO层(mybatis内部使用的是动态代理,所以我们不需要自己编写实现类)。

然而在实际开发中,单表操作非常多,如果你也想像JPA、JDBC那样做一个所谓的BaseDao。那么可以实现一个通用Mapper来达到目的。现在有现成的通用Mapper插件,我们无需重新创造轮子(代码是开源的,你也可以自己在其基础上修改)。

通用Mapper插件网址:https://github.com/abel533/Mapper

下面是使用方法(本文直接将分页插件PageHelper也集成了):
一、添加或修改pom依赖

            <!-- MyBatis -->
    <!-- <dependency> -->
    <!-- <groupId>org.mybatis.spring.boot</groupId> -->
    <!-- <artifactId>mybatis-spring-boot-starter</artifactId> -->
    <!-- <version>1.0.1-SNAPSHOT</version> -->
    <!-- </dependency> -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.3.0</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>1.2.3</version>
            </dependency>
            <!-- 分页插件 -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <version>4.1.1</version>
            </dependency>
            <!--通用Mapper插件-->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper</artifactId>
                <version>3.3.4</version>
            </dependency>

这里说一下,文章开始指定的那篇文章中直接依赖的mybatis的starter。因为本文在集成通用Mapper的时候直接使用出现了错误,所以将mybatis的starter中的Java类(它本身只有2个Java类,非常简单)拷贝到工程中,注释掉了头部的//@ConditionalOnBean(DataSource.class),你不用去找那2个类的源码了,下面会粘贴出来。

二、将下面4个Java类加入到工程中

将文件
MybatisAutoConfiguration.java
MyBatisMapperScannerConfig.java
MybatisProperties.java
MyMapper.java
添加到 org.springboot.sample.config.mybatis 中(包名根据自己工程修改)

最有一个MyMapper.java要特别注意,不要把MyMapper放到同其他Mapper一起,该类不能被当做普通Mapper一样被扫描,否则会出错。

    package org.springboot.sample.config.mybatis;

    import java.util.Properties;

    import javax.annotation.PostConstruct;
    import javax.sql.DataSource;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.ibatis.plugin.Interceptor;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.DefaultResourceLoader;
    import org.springframework.core.io.Resource;
    import org.springframework.core.io.ResourceLoader;
    import org.springframework.util.Assert;
    import org.springframework.util.StringUtils;

    import com.github.pagehelper.PageHelper;

    /** * {@link EnableAutoConfiguration Auto-Configuration} for Mybatis. Contributes a * {@link SqlSessionFactory} and a {@link SqlSessionTemplate}. * * If {@link org.mybatis.spring.annotation.MapperScan} is used, or a configuration file is * specified as a property, those will be considered, otherwise this auto-configuration * will attempt to register mappers based on the interface definitions in or under the * root auto-configuration package. * * @author Eddú Meléndez * @author Josh Long */
    @Configuration
    @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
    //@ConditionalOnBean(DataSource.class)
    @EnableConfigurationProperties(MybatisProperties.class)
    @AutoConfigureAfter(DataSourceAutoConfiguration.class)
    public class MybatisAutoConfiguration {

        private static Log log = LogFactory.getLog(MybatisAutoConfiguration.class);

        @Autowired
        private MybatisProperties properties;

        @Autowired(required = false)
        private Interceptor[] interceptors;

        @Autowired
        private ResourceLoader resourceLoader = new DefaultResourceLoader();

        @PostConstruct
        public void checkConfigFileExists() {
            if (this.properties.isCheckConfigLocation()) {
                Resource resource = this.resourceLoader
                        .getResource(this.properties.getConfig());
                Assert.state(resource.exists(),
                        "Cannot find config location: " + resource
                                + " (please add config file or check your Mybatis "
                                + "configuration)");
            }
        }

        @Bean(name = "sqlSessionFactory")
        @ConditionalOnMissingBean
        public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
            SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
            factory.setDataSource(dataSource);
            if (StringUtils.hasText(this.properties.getConfig())) {
                factory.setConfigLocation(
                        this.resourceLoader.getResource(this.properties.getConfig()));
            } else {
                if (this.interceptors != null && this.interceptors.length > 0) {
                    factory.setPlugins(this.interceptors);
                }
                factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
                factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
                factory.setMapperLocations(this.properties.getMapperLocations());
            }
            return factory.getObject();
        }

        @Bean
        @ConditionalOnMissingBean
        public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
            return new SqlSessionTemplate(sqlSessionFactory,
                    this.properties.getExecutorType());
        }

        /** * 分页插件 * * @param dataSource * @return * @author SHANHY * @create 2016年2月18日 */
        @Bean
        public PageHelper pageHelper(DataSource dataSource) {
            log.info("注册MyBatis分页插件PageHelper");
            PageHelper pageHelper = new PageHelper();
            Properties p = new Properties();
            p.setProperty("offsetAsPageNum", "true");
            p.setProperty("rowBoundsWithCount", "true");
            p.setProperty("reasonable", "true");
            pageHelper.setProperties(p);
            return pageHelper;
        }

    }
    package org.springboot.sample.config.mybatis;

    import java.util.Properties;

    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    import tk.mybatis.spring.mapper.MapperScannerConfigurer;

    /** * MyBatis扫描接口,使用的tk.mybatis.spring.mapper.MapperScannerConfigurer <br/> * 如果你不使用通用Mapper,可以改为org.xxx... * */
    @Configuration
    //TODO 注意,由于MapperScannerConfigurer执行的比较早,所以必须有下面的注解
    @AutoConfigureAfter(MybatisAutoConfiguration.class)
    public class MyBatisMapperScannerConfig {

        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer() {
            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
            mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
            mapperScannerConfigurer.setBasePackage("org.springboot.sample.mapper");
            Properties properties = new Properties();
            // 这里要特别注意,不要把MyMapper放到 basePackage 中,也就是不能同其他Mapper一样被扫描到。 
            properties.setProperty("mappers", MyMapper.class.getName());
            properties.setProperty("notEmpty", "false");
            properties.setProperty("IDENTITY", "MYSQL");
            mapperScannerConfigurer.setProperties(properties);
            return mapperScannerConfigurer;
        }

    }
    package org.springboot.sample.config.mybatis;

    import org.apache.ibatis.session.ExecutorType;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.core.io.Resource;

    /** * Configuration properties for Mybatis. * * @author Eddú Meléndez */
    @ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
    public class MybatisProperties {

        public static final String MYBATIS_PREFIX = "mybatis";

        /** * Config file path. */
        private String config;

        /** * Location of mybatis mapper files. */
        private Resource[] mapperLocations;

        /** * Package to scan domain objects. */
        private String typeAliasesPackage;

        /** * Package to scan handlers. */
        private String typeHandlersPackage;

        /** * Check the config file exists. */
        private boolean checkConfigLocation = false;

        /** * Execution mode. */
        private ExecutorType executorType = ExecutorType.SIMPLE;

        public String getConfig() {
            return this.config;
        }

        public void setConfig(String config) {
            this.config = config;
        }

        public Resource[] getMapperLocations() {
            return this.mapperLocations;
        }

        public void setMapperLocations(Resource[] mapperLocations) {
            this.mapperLocations = mapperLocations;
        }

        public String getTypeHandlersPackage() {
            return this.typeHandlersPackage;
        }

        public void setTypeHandlersPackage(String typeHandlersPackage) {
            this.typeHandlersPackage = typeHandlersPackage;
        }

        public String getTypeAliasesPackage() {
            return this.typeAliasesPackage;
        }

        public void setTypeAliasesPackage(String typeAliasesPackage) {
            this.typeAliasesPackage = typeAliasesPackage;
        }

        public boolean isCheckConfigLocation() {
            return this.checkConfigLocation;
        }

        public void setCheckConfigLocation(boolean checkConfigLocation) {
            this.checkConfigLocation = checkConfigLocation;
        }

        public ExecutorType getExecutorType() {
            return this.executorType;
        }

        public void setExecutorType(ExecutorType executorType) {
            this.executorType = executorType;
        }
    }
    package org.springboot.sample.config.mybatis;

    import tk.mybatis.mapper.common.Mapper;
    import tk.mybatis.mapper.common.MySqlMapper;

    /** * 被继承的Mapper,一般业务Mapper继承它 * */
    public interface MyMapper<T> extends Mapper<T>, MySqlMapper<T> {
        //TODO
        //FIXME 特别注意,该接口不能被扫描到,否则会出错
    }

三、属性配置文件
属性配置文件中和文章开头指定的文章一样配置,没有什么修改,下面粘贴出来:

    mybatis.mapper-locations=classpath*:org/springboot/sample/mapper/sql/mysql/*Mapper.xml
    mybatis.type-aliases-package=org.springboot.sample.entity

四、在业务Mapper中继承基础MyMapper接口

    public interface StudentMapper extends MyMapper<Student> {

        List<Student> likeName(String name);

        Student getById(int id);

        int add(Student stu);

        String getNameById(int id);

    }

然后在Service中使用即可,后面就没什么说的了。

    @Service
    public class StudentService {

        @Autowired
        private JdbcTemplate jdbcTemplate;

        @Autowired
        private StudentMapper studentMapper;

        @TargetDataSource(name="ds2")
        public List<Student> likeName(String name){
            return studentMapper.likeName(name);
        }

        public int testSave(){
            Student stu = new Student();
            stu.setAge(33);
            stu.setName("测试新增");
            stu.setSumScore("66");
            stu.setAvgScore("22");
            return studentMapper.insert(stu);//这里调用的是基础Mapper中的insert方法
        }

    }

最后还有一点要说明,使用公共Mapper“可能”需要对实体类进行修改。如果你的实体字段和数据库字段不一致(或者实体名称和数据库表名不一致),这样才需要修改,例如:

    /** * 学生实体 * * @author 单红宇(365384722) * @myblog http://blog.csdn.net/catoop/ * @create 2016年1月12日 */
    public class Student implements Serializable{

        @Id
        private int id;
        private String name;
        @Column(name="SCORE_SUM")
        private String sumScore;
        @Column(name="SCORE_AVG")
        private String avgScore;
        private int age;

        // getter setter 

    }

其他没有什么可说的了,请至少要到 https://github.com/abel533/Mapper 把插件的其他说明再看一遍。


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring Boot MyBatis 通用Mapper插件集成

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏