I. Project case introduction
1. Introduction to multi-data
In real projects, different databases are often used to meet the actual needs of the project. With the increasing concurrency of services, it is more and more common for a project to use multiple databases: master/slave replication, read/write separation, and distributed databases.
2. Introduction to MybatisPlus
MyBatis-Plus (MP for short) is a MyBatis enhancement tool, on the basis of MyBatis only do enhancement do not change, to simplify the development and improve efficiency.
Plug-in features
No code intrusion: only enhancements are made and no changes are made. Introducing it will not affect existing projects. Powerful CRUD operations: Most CRUD operations in a single table can be implemented with a few configurations to meet various requirements. Support Lambda form call: through Lambda expressions, it is convenient to write various query conditions. Supports automatic primary key generation: Can be configured freely to solve the primary key problem. Built-in code generator: Layers of code can be quickly generated using code or Maven plug-ins. Built-in paging plugin: Based on MyBatis physical paging, developers do not need to care about specific operations. Built-in performance analysis plug-in: output Sql statements and their execution time.
Copy the code
2. Multi-data source cases
1. Project structure
Note: mapper layer and mapper. XML layer are placed in different directories for myBatis scan loading.
2. Configure multiple data sources
Spring: # data source configuration datasource: type: com. Alibaba. Druid. Pool. DruidDataSource admin - data: driverClassName: . Com. Mysql. JDBC Driver dbUrl: JDBC: mysql: / / 127.0.0.1:3306 / cloud - admin - data? useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false username: root password: 123 initialSize: 20 maxActive: 100 minIdle: 20 maxWait: 60000 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 30 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 30000 maxEvictableIdleTimeMillis: 60000 validationQuery: SELECT 1 FROM DUAL testOnBorrow: false testOnReturn: false testWhileIdle: true connectionProperties: druid.stat.mergeSql=true; druid.stat.slowSqlMillis=5000 filters: stat,wall user-data: driverClassName: com.mysql.jdbc.Driver dbUrl: JDBC: mysql: / / 127.0.0.1:3306 / cloud - the user - the data? useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false username: root password: 123 initialSize: 20 maxActive: 100 minIdle: 20 maxWait: 60000 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 30 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 30000 maxEvictableIdleTimeMillis: 60000 validationQuery: SELECT 1 FROM DUAL testOnBorrow: false testOnReturn: false testWhileIdle: true connectionProperties: druid.stat.mergeSql=true; druid.stat.slowSqlMillis=5000 filters: stat,wall
Copy the code
The parameter forms are varied. You only need to configure parameter scanning.
3. Parameter scanning class
@Component@ConfigurationProperties(prefix = "spring.datasource.admin-data")public class DruidOneParam { private String dbUrl; private String username; private String password; private String driverClassName; private int initialSize; private int maxActive; private int minIdle; private int maxWait; private boolean poolPreparedStatements; private int maxPoolPreparedStatementPerConnectionSize; private int timeBetweenEvictionRunsMillis; private int minEvictableIdleTimeMillis; private int maxEvictableIdleTimeMillis; private String validationQuery; private boolean testWhileIdle; private boolean testOnBorrow; private boolean testOnReturn; private String filters; private String connectionProperties; // omit GET and SET}
Copy the code
4. Configure a Druid connection pool
@Configuration@MapperScan(basePackages = {"com.data.source.mapper.one"},sqlSessionTemplateRef = "sqlSessionTemplateOne")public class DruidOneConfig { private static final Logger LOGGER = LoggerFactory.getLogger(DruidOneConfig.class) ; @Resource private DruidOneParam druidOneParam ; @Bean("dataSourceOne") public DataSource dataSourceOne () { DruidDataSource datasource = new DruidDataSource(); datasource.setUrl(druidOneParam.getDbUrl()); datasource.setUsername(druidOneParam.getUsername()); datasource.setPassword(druidOneParam.getPassword()); datasource.setDriverClassName(druidOneParam.getDriverClassName()); datasource.setInitialSize(druidOneParam.getInitialSize()); datasource.setMinIdle(druidOneParam.getMinIdle()); datasource.setMaxActive(druidOneParam.getMaxActive()); datasource.setMaxWait(druidOneParam.getMaxWait()); datasource.setTimeBetweenEvictionRunsMillis(druidOneParam.getTimeBetweenEvictionRunsMillis()); datasource.setMinEvictableIdleTimeMillis(druidOneParam.getMinEvictableIdleTimeMillis()); datasource.setMaxEvictableIdleTimeMillis(druidOneParam.getMaxEvictableIdleTimeMillis()); datasource.setValidationQuery(druidOneParam.getValidationQuery()); datasource.setTestWhileIdle(druidOneParam.isTestWhileIdle()); datasource.setTestOnBorrow(druidOneParam.isTestOnBorrow()); datasource.setTestOnReturn(druidOneParam.isTestOnReturn()); datasource.setPoolPreparedStatements(druidOneParam.isPoolPreparedStatements()); datasource.setMaxPoolPreparedStatementPerConnectionSize(druidOneParam.getMaxPoolPreparedStatementPerConnectionSize()); try { datasource.setFilters(druidOneParam.getFilters()); } catch (Exception e) { LOGGER.error("druid configuration initialization filter", e); } datasource.setConnectionProperties(druidOneParam.getConnectionProperties()); return datasource; } @Bean public SqlSessionFactory sqlSessionFactoryOne() throws Exception{ SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); factory.setDataSource(dataSourceOne()); factory.setMapperLocations(resolver.getResources("classpath*:/dataOneMapper/*.xml")); return factory.getObject(); } @Bean(name="transactionManagerOne") public DataSourceTransactionManager transactionManagerOne(){ return new DataSourceTransactionManager(dataSourceOne()); } @Bean(name = "sqlSessionTemplateOne") public SqlSessionTemplate sqlSessionTemplateOne() throws Exception { return new SqlSessionTemplate(sqlSessionFactoryOne()); }}
Copy the code
Matters needing attention
-
MapperScan is configured on the specified data source.
-
SqlSessionFactory Configudes the scanned mapper. XML address;
-
DataSourceTransactionManager configure the data source of transaction;
-
The configuration methods of the two data sources are the same.
5. Operating cases
-
Data source 1: simple query
@Servicepublic class AdminUserServiceImpl implements AdminUserService { @Resource private AdminUserMapper adminUserMapper ; @Override public AdminUser selectByPrimaryKey (Integer id) { return adminUserMapper.selectByPrimaryKey(id) ; }}
Copy the code
-
Data source two: transaction operations
@Servicepublic class UserBaseServiceImpl implements UserBaseService { @Resource private UserBaseMapper userBaseMapper ; @Override public UserBase selectByPrimaryKey(Integer id) { return userBaseMapper.selectByPrimaryKey(id); } @transactional (value = "transactionManagerTwo") @override public void insert(UserBase record) {// Userbasemapper.insert (record); // int i = 1/0 ; }}
Copy the code
Note: Here you need to specify the transaction manager for the data source configuration.
Iii. MybatisPlus Case
1. Core dependencies
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> < version > 3.0.7.1 < / version > < exclusions > < exclusion > < groupId > com. Baomidou < / groupId > <artifactId>mybatis-plus-generator</artifactId> </exclusion> </exclusions></dependency><dependency> < the groupId > com. Baomidou < / groupId > < artifactId > mybatis - plus < / artifactId > < version > 3.0.7.1 < / version > < / dependency >
Copy the code
2. Configuration files
mybatis-plus: mapper-locations: classpath*:/mapper/*.xml typeAliasesPackage: com.digital.market.*.entity global-config: db-config: id-type: AUTO field-strategy: NOT_NULL logic-delete-value: -1 logic-not-delete-value: 0 banner: false configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true cache-enabled: false call-setters-on-nulls: true jdbc-type-for-null: 'null'
Copy the code
3. Layered configuration
UserBaseMapper extends BaseMapper<UserBase> Extends ServiceImpl<UserBaseMapper,UserBase> UserBaseService extends IService<UserBase>
Copy the code
Mapper. XML file
<mapper namespace="com.plus.batis.mapper.UserBaseMapper" > <resultMap id="BaseResultMap" type="com.plus.batis.entity.UserBase" > <id column="id" property="id" jdbcType="INTEGER" /> <result column="user_name" property="userName" jdbcType="VARCHAR" /> <result column="pass_word" property="passWord" jdbcType="VARCHAR" /> <result column="phone" property="phone" jdbcType="VARCHAR" /> <result column="email" property="email" jdbcType="VARCHAR" /> <result column="create_time" property="createTime" jdbcType="TIMESTAMP" /> <result column="update_time" property="updateTime" jdbcType="TIMESTAMP" /> <result column="state" property="state" jdbcType="INTEGER" /> </resultMap> <sql id="Base_Column_List" > id, user_name, pass_word, phone, email, create_time, update_time, state </sql> <select id="selectByParam" parameterType="com.plus.batis.entity.QueryParam" resultMap="BaseResultMap"> select * from hc_user_base </select></mapper>
Copy the code
Matters needing attention
Methods in BaseMapper are implemented by default; You can also customize your own methods here.
5. Demo interface
@RestController@RequestMapping("/user")public class UserBaseController { private static final Logger LOGGER = LoggerFactory.getLogger(UserBaseController.class) ; @Resource private UserBaseService userBaseService ; @RequestMapping("/info") public UserBase getUserBase (){ return userBaseService.getById(1) ; } @RequestMapping("/queryInfo") public String queryInfo (){ UserBase userBase1 = userBaseService.getOne(new QueryWrapper<UserBase>().orderByDesc("create_time")) ; Logger.info (" flashback value: {}", userbase1.getUsername ()); Integer count = userBaseService.count() ; Logger. info(" query total: {}",count); UserBase userBase2 = new UserBase() ; userBase2.setId(1); userBase2.setUserName("spring"); boolean resFlag = userBaseService.saveOrUpdate(userBase2) ; Logger. info(" Save updates: {}",resFlag); Map<String, Object> listByMap = new HashMap<>() ; listByMap.put("state","0") ; Collection<UserBase> listMap = userBaseService.listByMap(listByMap) ; Logger. info("ListByMap query: {}",listMap); boolean removeFlag = userBaseService.removeById(3) ; Logger. info(" Delete data: {}",removeFlag); return "success" ; } @RequestMapping("/queryPage") public IPage<UserBase> queryPage (){ QueryParam param = new QueryParam() ; param.setPage(1); param.setPageSize(10); param.setUserName("cicada"); param.setState(0); return userBaseService.queryPage(param) ; } @RequestMapping("/pageHelper") public PageInfo<UserBase> pageHelper (){ return userBaseService.pageHelper(new QueryParam()) ; }}
Copy the code
The pageHelper method here is a custom method using the pageHelper plugin.
Source code address
Making address https://github.com/cicadasmile/middle-ware-parentGitEE, https://gitee.com/cicadasmile/middle-ware-parent
Copy the code