描述
集成mybatis
首先要引入mybatis依赖
注解式开发
编写dao层,在接口中使用注解开发。
@Mapper
是mybatis的注解,在service层@Autowired
注入的时候爆红说该类没有初始化,可以使用@Resource
注解替换。
@Mapper
也可以不用,改用springboot启动类上的注解@MapperScan
@Mapper
public interface StudentDao {
@Select("select id,name,age,status,address from test")
List<Student> queryList(StudentCondition condition);
@Insert("insert into test (name,age,status,address) values (#{name},#{age},#{status},#{address})")
void insert(StudentCondition condition);
@Delete("delete from test where id=#{id}")
void delete(int id);
@Update("update test set name=#{name},age=#{age},status=#{status},address=#{address}")
void update(StudentCondition condition);
@Select("select id,name,age,status,address from test where id=#{id}")
//@ResultMap("studentMap") 该注解需要xml中书写resultmap
Student queryOne(int id);
}
配置式开发
在springboot application.yml中指定mapper-config.xml和mapper文件的位置。然后编写mapper文件
mybatis:
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
studentDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.redoor.springboot.demo.student.StudentXmlDao">
<select id="queryList" resultType="com.redoor.springboot.demo.student.Student">
select id,name,age,status,address from test
</select>
<select id="queryOne" resultType="com.redoor.springboot.demo.student.Student">
select id,name,age,status,address from test
<trim prefix="where" prefixOverrides="and | or">
<if test="id!=null">
id=#{id}
</if>
</trim>
</select>
<delete id="delete" parameterType="int">
delete from test where id=#{id}
</delete>
<insert id="insert" parameterType="com.redoor.springboot.demo.student.StudentCondition">
insert into test (name, age, status, address)
values (#{name}, #{age}, #{status}, #{address});
</insert>
<update id="update" parameterType="com.redoor.springboot.demo.student.StudentCondition">
update test
<trim prefix="set" suffixOverrides=",">
<if test="name!=null">name=#{name}</if>
<if test="age>0">age=#{age}</if>
<if test="status>0">status=#{status}</if>
<if test="address!=null">address=#{address}</if>
</trim>
where id=#{id}
</update>
</mapper>
多数据源配置
使用aop形式动态切换数据源
1.pom中增加aop依赖组,application.yml中配置两个数据源
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
spring:
db1:
url: jdbc:mysql://127.0.0.1:3306/text?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
db2:
url: jdbc:mysql://127.0.0.1:3306/text2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
2.编写aop工具类
- 自定义动态数据源类
DynamicDataSource
继承AbstractRoutingDataSource
,实现determineCurrentLookupKey()
数据源路由方法。
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDbName();
}
}
- 自定义aop切面类
DataSourceAspect
,拦截dao层方法,并获取自定义注解值。
@Component
@Aspect
@Slf4j
public class DataSourceAspect {
@Pointcut("execution(* com.redoor.springboot.demo.*.dao.*.*(..))")
public void dynamicDbPointCut() {}
@Before("dynamicDbPointCut()")
public void before(JoinPoint jp) {
try {
Class<?>[] interfaces = jp.getTarget().getClass().getInterfaces();
boolean classAnnotationPresent = interfaces[0].isAnnotationPresent(DbName.class);
boolean dbNameAnnotation = classAnnotationPresent;
String dbNameValue = null;
if (classAnnotationPresent) {
dbNameValue = interfaces[0].getAnnotation(DbName.class).value();
} else {
MethodSignature methodSignature = (MethodSignature) jp.getSignature();
Method method = methodSignature.getMethod();
boolean methodAnnotationPresent = method.isAnnotationPresent(DbName.class);
dbNameAnnotation = methodAnnotationPresent;
if (methodAnnotationPresent) {
dbNameValue = method.getAnnotation(DbName.class).value();
}
}
if (dbNameAnnotation && dbNameValue != null) {
DynamicDataSourceHolder.putDbName(dbNameValue);
log.info("aspect finished put" + dbNameValue);
}
} catch (Exception e) {
log.error("aspect exception", e.getMessage());
}
}
@After("dynamicDbPointCut()")
public void after() {
DynamicDataSourceHolder.removeDbName();
log.info("aspect finished remove ");
}
@AfterThrowing("dynamicDbPointCut()")
public void afterThrowing() {
DynamicDataSourceHolder.removeDbName();
log.info("aspect finished remove ");
}
}
原理:数据源初始化时定义好数据源名称DbName。aop切面拦截到dao层注解并获取注解中DbName值,再将其写入到ThreadLocal中。然后后期使用数据源的时候先调用determineCurrentLookupKey()从ThreadLocal中取出DbName,在根据DbName取出对应的数据源。
3.配置数据源工具类
将多个数据源配置到DynamicDataSource
中。
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.db1")
DataSource db1() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.db2")
DataSource db2() {
return DataSourceBuilder.create().build();
}
@Bean
public DynamicDataSource dynamicDataSource(@Qualifier("db1") DataSource db1, @Qualifier("db2") DataSource db2) {
HashMap<Object, Object> map = new HashMap<>(2);
map.put("db1", db1);
map.put("db2", db2);
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(map);
dynamicDataSource.setDefaultTargetDataSource(db1);
return dynamicDataSource;
}
@Bean
public DataSourceTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {
return new DataSourceTransactionManager(dynamicDataSource);
}
@Bean
public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/*.xml"));
return factoryBean.getObject();
}
}
引用
https://www.cnblogs.com/ityouknow/p/6037431.html
https://juejin.im/post/5d830944f265da03963bd153
http://tech.dianwoda.com/2018/03/28/spring-boot-aopfang-shi-shi-xian-duo-shu-ju-yuan-qie-huan/
https://blog.51cto.com/lavasoft/172292
引用
http://www.spring4all.com/article/246
这是一篇优雅的Springboot2.0使用手册
网友评论