SpringBoot(三)-Mybatis的集成使用

业务层搭建

  1. 在22_spparent下新建一个子项目Module为05_mybatis,添加入口类Application
  2. 在05_mybatis的pom.xml中添加依赖
    1. 参考:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
     <dependencies>
         <!--需要填写版本号 -->
         <dependency>
             <groupId>org.mybatis.spring.boot</groupId>
             <artifactId>mybatis-spring-boot-starter</artifactId>
             <version>2.1.3</version>
         </dependency>
         <!-- 不需要填写版本号 -->
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
         </dependency>
         <!--需要填写版本号 -->
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>druid-spring-boot-starter</artifactId>
             <version>1.2.1</version>
         </dependency>
         <!--使用thymeleaf-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-thymeleaf</artifactId>
         </dependency>
     </dependencies>
    
  3. 数据源配置
    1. 在resources下新建application.yml,设置数据源

       spring:
         datasource:
           type: com.alibaba.druid.pool.DruidDataSource
           driver-class-name: com.mysql.cj.jdbc.Driver
           username: root
           password: root
           url: jdbc:mysql://localhost:3306/test-mybatis?serverTimezone=UTC
           druid:
             initial-size: 5
             max-active: 10
      
    2. 数据源相关的配置,可以参考(在External Libraries下查找)

      1. spring-boot-autoconfigure.jar中的DataSourceProperties类
      2. druid-spring-boot-autoconfigure.jar中的DruidDataSourceWrapper类
  4. 新建各模块类
    1. domain

       //com.zh.domain.Skill
       //自动生成构造方法
       @Data
       //生成所有成员的构造函数
       @AllArgsConstructor
       //生成无参构造方法
       @NoArgsConstructor
       public class Skill {
           private Integer id;
           private Date createdTime;
           private String name;
           private Integer level;
       }
      
    2. dao

       public interface SkillDao {
           //这三个使用mapper.xml
           boolean save(Skill skill);
           boolean update(Skill skill);
           boolean remove(Integer id);
           //使用功能纯注解
           @Select("SELECT * FROM skill")
           List<Skill> list();
           @Select("SELECT * FROM skill WHERE id = #{id}")
           Skill get(Integer id);
       }
      
    3. service

       //com.zh.service.SkillService
       public interface SkillService {
           boolean save(Skill skill);
           List<Skill> list();
           Skill get(Integer id);
           boolean remove(Integer id);
       }
              
       //com.zh.service.impl.SkillServiceImpl
       @Service
       @Transactional
       public class SkillServiceImpl implements SkillService {
           @Autowired
           private SkillDao dao;
              
           @Override
           public boolean save(Skill skill) {
               Integer id = skill.getId();
               if (id == null || id < 1) {
                   return dao.save(skill);
               }
               return dao.update(skill);
           }
              
           @Override
           @Transactional(readOnly = true)
           public List<Skill> list() {
               return dao.list();
           }
              
           @Override
           @Transactional(readOnly = true)
           public Skill get(Integer id) {
               return dao.get(id);
           }
              
           @Override
           public boolean remove(Integer id) {
               return dao.remove(id);
           }
       }
      
    4. SkillController

       @RestController
       @RequestMapping("/skills")
       public class SkillController {
           @Autowired
           private SkillService service;
              
           @GetMapping("/list")
           public List<Skill> list() {
               return service.list();
           }
              
           @GetMapping("/get")
           public Skill get(Integer id) {
               return service.get(id);
           }
              
           @PostMapping("/save")
           public String save(Skill skill) {
               String[] msgs;
               Integer id = skill.getId();
               if (id != null && id > 0) {
                   msgs = new String[] {"更新成功", "更新失败"};
               } else {
                   msgs = new String[] {"添加成功", "添加失败"};
               }
               return service.save(skill) ? msgs[0] + "_" + skill.getId() : msgs[1];
           }
              
           @PostMapping("/remove")
           public String remove(Integer id) {
               return service.remove(id) ? "删除成功" : "删除失败";
           }
       }
      
    5. 在入口程序出设置扫描dao

       //com.zh.Application05
       @SpringBootApplication
       //扫描所有的dao
       @MapperScan("com.zh.dao")
       public class Application05 {
           public static void main(String[] args) {
               SpringApplication.run(Application05.class, args);
           }
       }
      
    6. 创建templates,在下面新建一个index.html

       <div>
           <a th:href="@{/skills/get(id=1)}" target="_blank">单个</a>
       </div>
              
       <div>
           <a th:href="@{/skills/list}" target="_blank">列表</a>
       </div>
              
       <div>
           保存
           <form th:action="@{/skills/save}" method="post">
               <input name="id" placeholder="id">
               <input name="name" placeholder="name">
               <input name="level" placeholder="level">
               <button type="submit">保存</button>
           </form>
       </div>
              
       <div>
           删除
           <form th:action="@{/skills/remove}" method="post">
               <input name="id" placeholder="id">
               <button type="submit">删除</button>
           </form>
       </div>
      

mybatis的相关配置

配置dao的映射文件

  1. 在resouces下新建一个mappers,然后在下面新建一个SkillDao.xml

     <mapper namespace="com.zh.dao.SkillDao">
          <!--useGeneratedKeys、keyProperty将数据插入后的主键设置为id值    -->
    <!--    <insert id="save" parameterType="Skill" useGeneratedKeys="true"-->
    <!--            keyProperty="id">-->
    <!--    useGeneratedKeys可以项目全局设置,否则每个插入方法都需要设置-->
         <insert id="save" parameterType="Skill"
                 keyProperty="id">
             INSERT INTO skill(name, level) VALUES (#{name}, #{level})
         </insert>
        
         <update id="update" parameterType="Skill">
             UPDATE skill SET name = #{name}, level = #{level} WHERE id = #{id}
         </update>
        
         <delete id="remove" parameterType="int">
             DELETE FROM skill WHERE id = #{id}
         </delete>
     </mapper>
    
  2. 在application.yml中做如下配置

     mybatis:
       # 告诉容器所有的dao的mapper映射文件位置
       # 之前讲过,如果不写这个的话,可以通过将dao.xml直接写在java.com.zh.dao下面,或者在resources下新建一个com.zh.dao包,放在这个包下
       mapper-locations: classpath:/mappers/*.xml
       # 给这个包下面的所有类都设置别名,别名为类名的小写字母,只有设置了,dao.xml中的注释才能直接使用skill
       type-aliases-package: com.zh.domain
    
    1. MyBatis相关的配置,可以参考:mybatis-spring-boot-autoconfigure.jar中的MyBatisProperties类
  3. 还有一种方式,将SkillDao.xml文件放到java.com.zh.dao下面,或者在resources下新建一个com.zh.dao包,放在这个包下

    1. application.yml中则不用配置这个mapper-locations: classpath:/mappers/*.xml

配置mybatis的核心配置文件

  1. 方法一:
    1. 在resouces下面新建一个mybatis-config.xml

       <configuration>
           <!-- 其他设置 -->
           <settings>
               <!-- 全局设置,使用新生成记录的主键作为id值 -->
               <setting name="useGeneratedKeys" value="true"/>
               <!-- 数据库:my_first_name -> Java:myFirstName -->
               <setting name="mapUnderscoreToCamelCase" value="true"/>
           </settings>
       </configuration>
      
    2. 在application.yml中配置

        mybatis:
          type-aliases-package: com.zh.domain
          # 告知mybatis的主配置文件的位置
          config-location: classpath:mybatis-config.xml
      
  2. 方法二:直接不需要创建mybatis-config.xml,直接在application.yml中配置

     mybatis:
       type-aliases-package: com.zh.domain
       configuration:
         # 数据库:my_first_name -> Java:myFirstName
         map-underscore-to-camel-case: true
         # 全局设置,使用新生成记录的主键
         use-generated-keys: true
    
  3. 方法三:使用纯注解
    1. 新建MyBatisConfig类

       //com.zh.cfg.MyBatisConfig
       @Configuration
       public class MyBatisConfig {
           @Bean
           public ConfigurationCustomizer customizer() {
               return (configuration) -> {
                   configuration.setMapUnderscoreToCamelCase(true);
                   //全局设置,使用新生成记录的主键
                   configuration.setUseGeneratedKeys(true);
               };
           }
       }
      

分析所有的bean是怎么被加入到容器的?

  1. @SpringBootApplication 注解内部包含@ComponentScan,该注解会扫描入口类所在的包名下的所有文件以及子文件
    1. @ComponentScan会自动扫描包路径下的@Controller、@Service、@Repository、@Component类,符合扫描规则的类会装配到spring容器中。
  2. @RestController、@Configuration、@Service 这些注解本质都包含了@Component 注解
  3. @MapperScan作用:一是自动实现对应包名下的dao接口类对应的实现类;二是将该实现类加入到容器中,尽管内部没有@Component,是通过代码实现加入的

Starter的命名规范

  1. 从上面示例的依赖可以看到,有些依赖需要版本号,有些不需要,为什么呢?

     <!--需要填写版本号 -->
     <dependency>
         <groupId>org.mybatis.spring.boot</groupId>
         <artifactId>mybatis-spring-boot-starter</artifactId>
         <version>2.1.3</version>
     </dependency>
     <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>druid-spring-boot-starter</artifactId>
         <version>1.2.1</version>
     </dependency>
     <!-- 不需要填写版本号 -->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
     </dependency>
    
    1. 原因是如果SpringBoot官方自已有封装,即自己提供,则不需要版本号,反之需要版本号
  2. SpringBoot官方提供的starter:spring-boot-starter-*
  3. 自定义的starter(非SpringBoot官方): *-spring-boot-starter
  4. 参考文档:https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using-boot-starter
Table of Contents