美文网首页
spring boot教程

spring boot教程

作者: 紫色红色黑色 | 来源:发表于2020-04-22 09:29 被阅读0次

描述

集成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使用手册

相关文章

网友评论

      本文标题:spring boot教程

      本文链接:https://www.haomeiwen.com/subject/vmoygctx.html