SpringBoot(三)-Mybatis的集成使用
业务层搭建
- 在22_spparent下新建一个子项目Module为05_mybatis,添加入口类Application
- 在05_mybatis的pom.xml中添加依赖
<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>
- 数据源配置
-
在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
-
数据源相关的配置,可以参考(在External Libraries下查找)
- spring-boot-autoconfigure.jar中的DataSourceProperties类
- druid-spring-boot-autoconfigure.jar中的DruidDataSourceWrapper类
-
- 新建各模块类
-
domain
//com.zh.domain.Skill //自动生成构造方法 @Data //生成所有成员的构造函数 @AllArgsConstructor //生成无参构造方法 @NoArgsConstructor public class Skill { private Integer id; private Date createdTime; private String name; private Integer level; }
-
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); }
-
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); } }
-
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) ? "删除成功" : "删除失败"; } }
-
在入口程序出设置扫描dao
//com.zh.Application05 @SpringBootApplication //扫描所有的dao @MapperScan("com.zh.dao") public class Application05 { public static void main(String[] args) { SpringApplication.run(Application05.class, args); } }
-
创建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的映射文件
-
在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>
-
在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
- MyBatis相关的配置,可以参考:
mybatis-spring-boot-autoconfigure.jar
中的MyBatisProperties类
- MyBatis相关的配置,可以参考:
-
还有一种方式,将SkillDao.xml文件放到java.com.zh.dao下面,或者在resources下新建一个com.zh.dao包,放在这个包下
- application.yml中则不用配置这个
mapper-locations: classpath:/mappers/*.xml
- application.yml中则不用配置这个
配置mybatis的核心配置文件
- 方法一:
-
在resouces下面新建一个mybatis-config.xml
<configuration> <!-- 其他设置 --> <settings> <!-- 全局设置,使用新生成记录的主键作为id值 --> <setting name="useGeneratedKeys" value="true"/> <!-- 数据库:my_first_name -> Java:myFirstName --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> </configuration>
-
在application.yml中配置
mybatis: type-aliases-package: com.zh.domain # 告知mybatis的主配置文件的位置 config-location: classpath:mybatis-config.xml
-
-
方法二:直接不需要创建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
- 方法三:使用纯注解
-
新建MyBatisConfig类
//com.zh.cfg.MyBatisConfig @Configuration public class MyBatisConfig { @Bean public ConfigurationCustomizer customizer() { return (configuration) -> { configuration.setMapUnderscoreToCamelCase(true); //全局设置,使用新生成记录的主键 configuration.setUseGeneratedKeys(true); }; } }
-
分析所有的bean是怎么被加入到容器的?
@SpringBootApplication
注解内部包含@ComponentScan
,该注解会扫描入口类所在的包名下的所有文件以及子文件@ComponentScan
会自动扫描包路径下的@Controller、@Service、@Repository、@Component
类,符合扫描规则的类会装配到spring容器中。
@RestController、@Configuration、@Service
这些注解本质都包含了@Component
注解@MapperScan
作用:一是自动实现对应包名下的dao接口类对应的实现类;二是将该实现类加入到容器中,尽管内部没有@Component
,是通过代码实现加入的
Starter的命名规范
-
从上面示例的依赖可以看到,有些依赖需要版本号,有些不需要,为什么呢?
<!--需要填写版本号 --> <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>
- 原因是如果SpringBoot官方自已有封装,即自己提供,则不需要版本号,反之需要版本号
- SpringBoot官方提供的starter:
spring-boot-starter-*
- 自定义的starter(非SpringBoot官方):
*-spring-boot-starter
- 参考文档:https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using-boot-starter