springboot2.x整合mybatis、druid、tk.mybatis及pagehelper

前言

由于使用nacos作为配置中心,方便配置统一管理,因此尽可能简化application.yml中的配置,改用注解的方式进行配置。

1.添加依赖

我用的spring-boot是2.1.6.RELEASE版本

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  
  <dependency>
      <groupId>tk.mybatis</groupId>
      <artifactId>mapper-spring-boot-starter</artifactId>
  </dependency>
  
  <!--数据库持久化相关 begin-->
  <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
  </dependency>

  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
  </dependency>

  <!-- 分页插件 -->
  <dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
  </dependency>
  
  <!-- alibaba的druid数据库连接池 -->
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
  </dependency>
  <!--数据库持久化相关 end-->

用起步依赖是因为他们是你使用的springboot版本的最佳实践,一版情况下不需要考虑依赖之间兼容性的问题

2.数据源

从nacos中取出数据库配置

@Data
@RefreshScope
@Configuration
public class JdbcMapper {

  @Value("${jdbc.driverClassName}")
  private String driverClassName;
  @Value("${jdbc.url}")
  private String url;
  @Value("${jdbc.username}")
  private String username;
  @Value("${jdbc.password}")
  private String password;
  @Value("${jdbc.initialSize}")
  private Integer initialSize;
  @Value("${jdbc.maxActive}")
  private Integer maxActive;
  @Value("${jdbc.minPoolSize}")
  private Integer minPoolSize;
  @Value("${jdbc.maxWait}")
  private Long maxWait;
  @Value("${jdbc.minIdle}")
  private Integer minIdle;
  @Value("${jdbc.timeBetweenEvictionRunsMillis}")
  private Long timeBetweenEvictionRunsMillis;
  @Value("${jdbc.minEvictableIdleTimeMillis}")
  private Long minEvictableIdleTimeMillis;
  @Value("${jdbc.validationQuery}")
  private String validationQuery;
  @Value("${jdbc.testWhileIdle}")
  private Boolean testWhileIdle;
  @Value("${jdbc.testOnBorrow}")
  private Boolean testOnBorrow;
  @Value("${jdbc.testOnReturn}")
  private Boolean testOnReturn;
  @Value("${jdbc.maxOpenPreparedStatements}")
  private Integer maxOpenPreparedStatements;
  @Value("${jdbc.removeAbandoned}")
  private Boolean removeAbandoned;
  @Value("${jdbc.removeAbandonedTimeout}")
  private Integer removeAbandonedTimeout;
  @Value("${jdbc.logAbandoned}")
  private Boolean logAbandoned;
  @Value("${jdbc.poolPreparedStatements}")
  private Boolean poolPreparedStatements;
  @Value("${jdbc.filters}")
  private String filters;
  @Value("${jdbc.dbName}")
  private String dbName;
}

创建数据库连接池

@Configuration
public class DatabaseConfig {

  @Autowired
  @Lazy
  private JdbcMapper jdbcMapper;

  @Bean(name = "mysqlSource")
  @Primary
  public DataSource dataSource() {
    DruidDataSource datasource = new DruidDataSource();
    datasource.setDriverClassName(jdbcMapper.getDriverClassName());
    datasource.setUrl(jdbcMapper.getUrl());
    datasource.setUsername(jdbcMapper.getUsername());
    datasource.setPassword(jdbcMapper.getPassword());
    datasource.setInitialSize(jdbcMapper.getInitialSize());
    datasource.setMaxActive(jdbcMapper.getMaxActive());
    datasource.setMaxWait(jdbcMapper.getMaxWait());
    datasource.setMinIdle(jdbcMapper.getMinIdle());
    datasource.setTimeBetweenEvictionRunsMillis(jdbcMapper.getTimeBetweenEvictionRunsMillis());
    datasource.setMinEvictableIdleTimeMillis(jdbcMapper.getMinEvictableIdleTimeMillis());
    datasource.setValidationQuery(jdbcMapper.getValidationQuery());
    datasource.setTestWhileIdle(jdbcMapper.getTestWhileIdle());
    datasource.setTestOnBorrow(jdbcMapper.getTestOnBorrow());
    datasource.setTestOnReturn(jdbcMapper.getTestOnReturn());
    datasource.setMaxOpenPreparedStatements(jdbcMapper.getMaxOpenPreparedStatements());
    datasource.setRemoveAbandoned(jdbcMapper.getRemoveAbandoned());
    datasource.setRemoveAbandonedTimeout(jdbcMapper.getRemoveAbandonedTimeout());
    datasource.setLogAbandoned(jdbcMapper.getLogAbandoned());
    List<Filter> list = new ArrayList();
    list.add(new StatFilter());
    WallFilter wallFilter = new WallFilter();
    WallConfig config = new WallConfig();
    config.setMultiStatementAllow(true);
    wallFilter.setConfig(config);
    list.add(wallFilter);
    datasource.setProxyFilters(list);

    return datasource;

  }


  @Bean
  public ServletRegistrationBean druidServlet() {
    ServletRegistrationBean reg = new ServletRegistrationBean();
    reg.setServlet(new StatViewServlet());
    reg.addUrlMappings("/druid/base/*");
    reg.addInitParameter("loginUsername", "druid");
    reg.addInitParameter("loginPassword", "jiajian123456");
    return reg;
  }

  @Bean
  public FilterRegistrationBean filterRegistrationBean() {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    filterRegistrationBean.setFilter(new WebStatFilter());
    filterRegistrationBean.addUrlPatterns("/*");
    filterRegistrationBean
        .addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
    filterRegistrationBean.addInitParameter("profileEnable", "true");
    filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
    filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
    return filterRegistrationBean;
  }

}

3.mybatis配置

@Configuration
@EnableTransactionManagement
@MapperScan("com.capture.provider.mapper")
public class MyBatisConfig {

    @Resource
    DataSource dataSource;

    @Bean
    @Primary
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage("com.capture.model.po");
        //分页插件
        PageInterceptor pageHelper = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("helperDialect", "mysql");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);

        //添加插件
        sessionFactory.setPlugins(new Interceptor[]{pageHelper});

        //添加XML目录
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            sessionFactory.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
            return sessionFactory.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    @Bean
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }


    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }


}

创建会话工厂时添加分页插件,指定mybatis的xml所在的位置
注意在MyBatisConfig类的上面添加的@MapperScan注解是tk.mybatis的注解,用来指定mapper接口所在的位置,用org.mybatis的@MapperScan注解是不能实现tk.mybatis提供的功能的

4.tk.mybatis使用

1.创建数据操作接口

public interface BaseMapper <T> extends tk.mybatis.mapper.common.BaseMapper<T>, MySqlMapper<T>,
    IdsMapper<T>, ConditionMapper<T>,ExampleMapper<T>,RowBoundsMapper<T> {

}

2.创建通用service层接口

/**
 * 通用接口
 *
 * @param <T> the type parameter @author paascloud.net@gmail.com
 *
 * @author paascloud.net@gmail.com
 */
public interface IBaseService<T> {
	/**
	 * 根据实体中的属性值进行查询, 查询条件使用等号  @param record the record
	 *
	 * @param record the record
	 *
	 * @return the list
	 */
	List<T> select(T record);

	/**
	 * 根据主键字段进行查询, 方法参数必须包含完整的主键属性, 查询条件使用等号  @param key the key
	 *
	 * @param key the key
	 *
	 * @return the t
	 */
	T selectByPrimaryKey(Object key);

	/**
	 * 查询全部结果, select(null)方法能达到同样的效果  @return the list
	 *
	 * @return the list
	 */
	List<T> selectAll();

	/**
	 * 根据实体中的属性进行查询, 只能有一个返回值, 有多个结果是抛出异常, 查询条件使用等号  @param record the record
	 *
	 * @param record the record
	 *
	 * @return the t
	 */
	T selectOne(T record);

	/**
	 * 根据实体中的属性查询总数, 查询条件使用等号  @param record the record
	 *
	 * @param record the record
	 *
	 * @return the int
	 */
	int selectCount(T record);

	/**
	 * 保存一个实体, null的属性不会保存, 会使用数据库默认值  @param record the record
	 *
	 * @param record the record
	 *
	 * @return the int
	 */
	int save(T record);

	/**
	 * 批量保存  @param list the list
	 *
	 * @param list the list
	 *
	 * @return the int
	 */
	@Transactional(rollbackFor = Exception.class)
	int batchSave(List<T> list);

	/**
	 * 根据主键更新属性不为null的值  @param entity the entity
	 *
	 * @param entity the entity
	 *
	 * @return the int
	 */
	int update(T entity);

	/**
	 * 根据实体属性作为条件进行删除, 查询条件使用等号  @param record the record
	 *
	 * @param record the record
	 *
	 * @return the int
	 */
	int delete(T record);

	/**
	 * 批量删除  @param list the list
	 *
	 * @param list the list
	 *
	 * @return the int
	 */
	@Transactional(rollbackFor = Exception.class)
	int batchDelete(List<T> list);

	/**
	 * 根据主键字段进行删除, 方法参数必须包含完整的主键属性  @param key the key
	 *
	 * @param key the key
	 *
	 * @return the int
	 */
	int deleteByKey(Object key);

	/**
	 * 这个查询支持通过Example类指定查询列, 通过selectProperties方法指定查询列  @param example the example
	 *
	 * @param example the example
	 *
	 * @return the list
	 */
	List<T> selectByExample(Object example);

	/**
	 * 根据Example条件进行查询总数  @param example the example
	 *
	 * @param example the example
	 *
	 * @return the int
	 */
	int selectCountByExample(Object example);

	/**
	 * 根据Example条件更新实体record包含的不是null的属性值  @param record the record
	 *
	 * @param record  the record
	 * @param example the example
	 *
	 * @return the int
	 */
	int updateByExample(@Param("record") T record, @Param("example") Object example);

	/**
	 * 根据Example条件删除数据  @param example the example
	 *
	 * @param example the example
	 *
	 * @return the int
	 */
	int deleteByExample(Object example);

	/**
	 * 根据实体属性和RowBounds进行分页查询  @param record the record
	 *
	 * @param record    the record
	 * @param rowBounds the row bounds
	 *
	 * @return the list
	 */
	List<T> selectByRowBounds(T record, RowBounds rowBounds);

	/**
	 * 根据example条件和RowBounds进行分页查询  @param example the example
	 *
	 * @param example   the example
	 * @param rowBounds the row bounds
	 *
	 * @return the list
	 */
	List<T> selectByExampleAndRowBounds(Object example, RowBounds rowBounds);

}

3.创建通用service层接口实现

@Slf4j
public abstract class BaseBaseServiceImpl<T> implements IBaseService<T> {

  @Autowired
  protected BaseMapper<T> mapper;

  /**
   * Select list.
   *
   * @param record the record
   *
   * @return the list
   */
  @Override
  public List<T> select(T record) {
    return mapper.select(record);
  }

  /**
   * Select by key t.
   *
   * @param key the key
   *
   * @return the t
   */
  @Override
  public T selectByPrimaryKey(Object key) {
    return mapper.selectByPrimaryKey(key);
  }

  /**
   * Select all list.
   *
   * @return the list
   */
  @Override
  public List<T> selectAll() {
    return mapper.selectAll();
  }

  /**
   * Select one t.
   *
   * @param record the record
   *
   * @return the t
   */
  @Override
  public T selectOne(T record) {
    return mapper.selectOne(record);
  }

  /**
   * Select count int.
   *
   * @param record the record
   *
   * @return the int
   */
  @Override
  public int selectCount(T record) {
    return mapper.selectCount(record);
  }

  /**
   * Select by example list.
   *
   * @param example the example
   *
   * @return the list
   */
  @Override
  public List<T> selectByExample(Object example) {
    return mapper.selectByExample(example);
  }

  /**
   * Save int.
   *
   * @param record the record
   *
   * @return the int
   */
  @Override
  public int save(T record) {
    return mapper.insertSelective(record);
  }

  /**
   * Batch save int.
   *
   * @param list the list
   *
   * @return the int
   */
  @Override
  public int batchSave(List<T> list) {
    int result = 0;
    for (T record : list) {
      int count = mapper.insertSelective(record);
      result += count;
    }
    return result;
  }

  /**
   * Update int.
   *
   * @param entity the entity
   *
   * @return the int
   */
  @Override
  public int update(T entity) {
    return mapper.updateByPrimaryKeySelective(entity);
  }

  /**
   * Delete int.
   *
   * @param record the record
   *
   * @return the int
   */
  @Override
  public int delete(T record) {
    return mapper.delete(record);
  }

  /**
   * Delete by key int.
   *
   * @param key the key
   *
   * @return the int
   */
  @Override
  public int deleteByKey(Object key) {
    return mapper.deleteByPrimaryKey(key);
  }

  /**
   * Batch delete int.
   *
   * @param list the list
   *
   * @return the int
   */
  @Override
  public int batchDelete(List<T> list) {
    int result = 0;
    for (T record : list) {
      int count = mapper.deleteByPrimaryKey(record);
      if (count < 1) {
        log.error("删除数据失败");
        throw new BusinessException(ErrorCodeEnum.ERROR_DB_INSERT_FAIL);
      }
      result += count;
    }
    return result;
  }

  /**
   * Select count by example int.
   *
   * @param example the example
   *
   * @return the int
   */
  @Override
  public int selectCountByExample(Object example) {
    return mapper.selectCountByExample(example);
  }

  /**
   * Update by example int.
   *
   * @param record  the record
   * @param example the example
   *
   * @return the int
   */
  @Override
  public int updateByExample(T record, Object example) {
    return mapper.updateByExampleSelective(record, example);
  }

  /**
   * Delete by example int.
   *
   * @param example the example
   *
   * @return the int
   */
  @Override
  public int deleteByExample(Object example) {
    return mapper.deleteByPrimaryKey(example);
  }

  /**
   * Select by row bounds list.
   *
   * @param record    the record
   * @param rowBounds the row bounds
   *
   * @return the list
   */
  @Override
  public List<T> selectByRowBounds(T record, RowBounds rowBounds) {
    return mapper.selectByRowBounds(record, rowBounds);
  }

  /**
   * Select by example and row bounds list.
   *
   * @param example   the example
   * @param rowBounds the row bounds
   *
   * @return the list
   */
  @Override
  public List<T> selectByExampleAndRowBounds(Object example, RowBounds rowBounds) {
    return mapper.selectByExampleAndRowBounds(example, rowBounds);
  }

}

4.创建实体类

@Data
@Table(name="bdc_account")//设置数据库中表名字
public class BdcAccount implements Serializable {

  private static final long serialVersionUID = 1130119242372588401L;

  @Id
  private Integer id;

  private String url;

  private String website;

  private String username;

  private String password;

}

5.继承数据操作接口

public interface BdcAccountMapper extends BaseMapper<BdcAccount> {

  List<BdcAccount> getBdcAccountList();

}

6.创建接口对应的xml

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.capture.provider.mapper.BdcProductPublishMapper">
</mapper>

7.在service层不写sql直接操作单表

@Service
@Slf4j
public class BdcAccountBaseServiceImpl extends BaseBaseServiceImpl<BdcAccount> implements
    BdcAccountBaseService {

  @Resource
  private BdcAccountMapper bdcAccountMapper;

  @Override
  public BdcAccount selectByPrimaryKey() {
    BdcAccount account = new BdcAccount();
    account.setId(1);
    account = bdcAccountMapper.selectByPrimaryKey(account);
    return account;
  }
}

8.service层只要继承一下通用service层接口实现

@Service
@Slf4j
public class BdcProductPublishBaseServiceImpl extends
    BaseBaseServiceImpl<BdcProductPublish> implements
    BdcProductPublishBaseService {

}

9.直接调用通用service的方法操作单表

@RestController
public class BdcProductPublishQueryFeignClient {

  @Resource
  private BdcProductPublishBaseService bdcProductPublishService;

  public BdcProductPublishVo getBdcProductPublishVo(Integer publishId) {
    BdcProductPublish publish = new BdcProductPublish();
    publish.setId(publishId);
    return bdcProductPublishService.selectByPrimaryKey(publish);
  }
}

5.小结

至此,我们就可以把单表那些枯燥无聊重复的代码抛到脑后了;如果需要写一些多表关联的复杂sql,你开始可以写在mapper对应的xml中,正常使用mybatis调用即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值