由于使用nacos作为配置中心,方便配置统一管理,因此尽可能简化application.yml中的配置,改用注解的方式进行配置。
我用的spring-boot是2.1.6.RELEASE版本
org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE
tk.mybatis
mapper-spring-boot-starter
org.mybatis.spring.boot
mybatis-spring-boot-starter
mysql
mysql-connector-java
runtime
com.github.pagehelper
pagehelper-spring-boot-starter
com.alibaba
druid-spring-boot-starter
用起步依赖是因为他们是你使用的springboot版本的最佳实践,一版情况下不需要考虑依赖之间兼容性的问题
从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 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;
}
}
@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提供的功能的
1.创建数据操作接口
public interface BaseMapper extends tk.mybatis.mapper.common.BaseMapper, MySqlMapper,
IdsMapper, ConditionMapper,ExampleMapper,RowBoundsMapper {
}
2.创建通用service层接口
/**
* 通用接口
*
* @param the type parameter @author [email protected]
*
* @author [email protected]
*/
public interface IBaseService {
/**
* 根据实体中的属性值进行查询, 查询条件使用等号 @param record the record
*
* @param record the record
*
* @return the list
*/
List 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 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 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 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 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 selectByRowBounds(T record, RowBounds rowBounds);
/**
* 根据example条件和RowBounds进行分页查询 @param example the example
*
* @param example the example
* @param rowBounds the row bounds
*
* @return the list
*/
List selectByExampleAndRowBounds(Object example, RowBounds rowBounds);
}
3.创建通用service层接口实现
@Slf4j
public abstract class BaseBaseServiceImpl implements IBaseService {
@Autowired
protected BaseMapper mapper;
/**
* Select list.
*
* @param record the record
*
* @return the list
*/
@Override
public List 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 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 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 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 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 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 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 {
List getBdcAccountList();
}
6.创建接口对应的xml
7.在service层不写sql直接操作单表
@Service
@Slf4j
public class BdcAccountBaseServiceImpl extends BaseBaseServiceImpl 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 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);
}
}
至此,我们就可以把单表那些枯燥无聊重复的代码抛到脑后了;如果需要写一些多表关联的复杂sql,你开始可以写在mapper对应的xml中,正常使用mybatis调用即可。