Spring Boot MyBatis 通用Mapper插件集成

vedx8423 8年前發布 | 160K 次閱讀 Spring JEE框架

來自: http://blog.csdn.net/catoop/article/details/50684676


看本文之前,請確保你已經在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;
}

}</pre>

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;
}

}</pre>

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;
}

}</pre>

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 特別注意,該接口不能被掃描到,否則會出錯 }</pre>

三、屬性配置文件
屬性配置文件中和文章開頭指定的文章一樣配置,沒有什么修改,下面粘貼出來:

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);

}</pre>

然后在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方法
}

}</pre>

最后還有一點要說明,使用公共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 

}</pre>

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

</div>

 本文由用戶 vedx8423 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!