在Mybatis初期 需要配置实体类、 配置映射文件 、DAO层代码等一大堆配置. 当然Mybatis 为了解决这些弊端开发了generator 可以根据数据库-数据表自动生成实体类、配置文件和dao层代码,减轻了一部分开发量. MyBatis还提供了注解的方式,适用于小型项目,不用在写配置文件,但是需要在注解上写SQL语句不利于管理. Spring Boot 化繁为简提供了mybatis-spring-boot-starter 可以轻松配置上手.

mybatis-spring-boot-starter 是Mybatis 整合Spring Boot的一套解决方案. 官方的:MyBatis Spring-Boot-Starter will help you use MyBatis with Spring Boot. 官方地址

  1. 首先构建一个Spring Web的Spring Boot项目. 在pom文件中,引入mybatis-spring-boot-starter 依赖包括mysql驱动.spring-boot-starter-web 引入的spring-mvc的依赖实现restful.

    1. <!-- mybatis整合springboot的依赖 -->
    2. <dependency>
    3. <groupId>org.mybatis.spring.boot</groupId>
    4. <artifactId>mybatis-spring-boot-starter</artifactId>
    5. <version>2.1.0</version>
    6. </dependency>
    7. <dependency>
    8. <groupId>org.springframework.boot</groupId>
    9. <artifactId>spring-boot-starter-web</artifactId>
    10. </dependency>
    11. <!-- 引入mysql驱动依赖 -->
    12. <dependency>
    13. <groupId>mysql</groupId>
    14. <artifactId>mysql-connector-java</artifactId>
    15. <version>8.0.19</version>
    16. </dependency>
  2. 在application.yml中配置,端口信息 数据源信息以及mybatis的配置(配置pojo实体类所在的包路径)

  1. server:
  2. port: 8089
  3. tomcat:
  4. uri-encoding: UTF-8
  5. ##############################################
  6. 配置数据源 自动注入sqlSessionFactory
  7. #############################################
  8. spring:
  9. datasource:
  10. driver-class-name: com.mysql.jdbc.Driver
  11. url: jdbc:mysql://localhost:3306/foodie-shop?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
  12. username: root
  13. password: root
  14. ##################################
  15. mybatis 配置
  16. ##################################
  17. mybatis:
  18. type-aliases-package: com.prim.demo.t_spring_boot_mybatis.pojo #配置pojo所在包的路径

Spring Boot 会自动加载spring.datasource.* 的数据源配置,并且会自动注入到SqlSessionFactory中.

如果你还不理解,看一看原始的MyBatis加载配置操作,通过SqlSessionFactoryBuilder加载配置,Spring Boot帮助我们大大简化了操作,只需要关注配置文件的维护,Spring Boot内部已经自动加载注入到SqlSessionFactory中了.

  1. private static SqlSessionFactory sqlSessionFactory = null;
  2. static {
  3. try {
  4. //加载xml配置文件
  5. Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
  6. //得到SqlSessionFactory
  7. sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
  8. } catch (IOException e) {
  9. e.printStackTrace();
  10. throw new ExceptionInInitializerError(e);
  11. }
  12. }
  13. public static SqlSession openSession(){
  14. return sqlSessionFactory.openSession();
  15. }
  16. /**
  17. * 设置SQL是否自动提交事务,一般对于数据库的写操作:插入 更新 删除 都需要手动提交事务来保证数据的完整性
  18. * @param isAutoCommit
  19. * @return
  20. */
  21. public static SqlSession openSession(boolean isAutoCommit){
  22. //默认情况下自动提交事务
  23. //false 关闭自动提交 需要手动提交事务
  24. return sqlSessionFactory.openSession(isAutoCommit);
  25. }
  26. public static void closeSession(SqlSession sqlSession){
  27. if (sqlSession != null){
  28. sqlSession.close();
  29. }
  30. }

在启动类中添加对Mapper包的扫描注解@MapperScan

@SpringBootApplication
@MapperScan(basePackages = "com.prim.demo.t_spring_boot_mybatis.mapper") 
//扫描mapper 或者在每个Mapper类上加入@Mapper注解不推荐这样使用推荐直接配置包名
public class TSpringBootMybatisApplication {
    public static void main(String[] args) {
        SpringApplication.run(TSpringBootMybatisApplication.class, args);
    }
}

通过配置mapper包,SpringBoot 会自动将mapper注入到SqlSession中,并且我们在使用时可直接获得实体对象调用.类似原始的方法:

<!-- 采用注解方式 两种方式为了更好的进行维护建议采用package的方式 -->
    <mappers>
<!--        <mapper class="com.prim.dao.GoodsDAO"/>-->
        <package name="com.prim.dao"/>
    </mappers>

public void selectDao(){
        SqlSession sqlSession = null;
        try {
            sqlSession = com.prim.utils.MyBatisUtils.openSession();
            GoodsDAO mapper = sqlSession.getMapper(GoodsDAO.class);
            List<Goods> list = mapper.selectPriceRange(100, 500, 20);
            System.out.println(list.size());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            com.prim.utils.MyBatisUtils.closeSession(sqlSession);
        }
    }

在Spring Boot中将这些操作,全部在内部处理了,只需通过注入Mapper即可使用.

使用注解的方式

Mapper类,通过注解的方式输入SQL语句

public interface StuMapper {

    @Insert("INSERT INTO stu(name,age) VALUES(#{name},#{age})")
    void save(Stu stu);

    @Update("UPDATE stu SET name=#{name},age=#{age} where id=#{id}")
    void update(Stu stu);

    @Results(id = "resultMap", value = {
            @Result(property = "id", column = "id", id = true),
            @Result(property = "name", column = "name"),
            @Result(property = "age", column = "age")
    })
    @Select("SELECT * FROM stu WHERE id=#{id}")
    Stu selectOne(int id);

    @ResultMap("resultMap")
    @Select("SELECT * FROM stu")
    List<Stu> selectAll();

    @Delete("DELETE FROM stu WHERE id=#{id}")
    void delete(int id);
}
  • @Select 查询类的注解,所有的查询操作
  • @Results 修饰返回的结果集,关联实体类属性和数据库中的字段,可通过设置id,其他方法的查询结果集可以复用
  • @Insert 插入数据操作
  • @Update 修改数据操作
  • @Delete 删除数据操作

注意:一定要使用#符号不要使用$符号,因为$符号有SQL注入攻击的漏洞

#符号类似:SELECT * FROM stu WHERE id=?
$符号类似:SELECT * FROM stu WHERE id='id'

构建业务成Service,@Service 注入业务类,通过@Autowired注入mapper对象

@Service
public class StuServiceImpl implements StuService {
    @Autowired
    private StuMapper stuMapper;

    @Override
    public void save() {
        Stu stu = new Stu();
        stu.setName("test-1");
        stu.setAge(32);
        stuMapper.save(stu);
    }

    @Override
    public void update(int id) {
        Stu stu = new Stu();
        stu.setId(id);
        stu.setName("update-1");
        stu.setAge(28);
        stuMapper.update(stu);
    }

    @Override
    public void delete(int id) {
        stuMapper.delete(id);
    }

    @Override
    public Stu getOne(int id) {
        return stuMapper.selectOne(id);
    }

    @Override
    public List<Stu> getAll() {
        return stuMapper.selectAll();
    }
}

在api层也就是controller层使用

@RestController
public class TestController {

    @Autowired
    private StuService stuService;

    @GetMapping("/getStu")
    public Object getStu(int id) {
        return stuService.getOne(id);
    }

    @PostMapping("/add")
    public Object addStu() {
        stuService.save();
        return "保存 ok";
    }

    @PostMapping("/update")
    public Object updateStu(int id) {
        stuService.update(id);
        return "更新 ok";
    }

    @PostMapping("/delete")
    public Object deleteStu(int id) {
        stuService.delete(id);
        return "删除 ok";
    }
}

极简XML方式

通过XML的方式,不需要在Java类中通过注解写SQL语句,而是和Java代码分离,通过XML的方式映射文件,mapper只需要定义空方法即可

  1. 配置mybatis的xml方式 在application.yml中配置映射文件路径和mybatis的配置文件路径,Spring Boot会自动装配这些配置
mybatis:
type-aliases-package: com.prim.demo.t_spring_boot_mybatis.pojo #配置pojo所在包的路径
mapper-locations: classpath:mapper/*.xml                       #映射文件的路径
config-location: classpath:mybatis/mybatis-config.xml          #mybatis配置文
  1. 配置映射文件 其实就是将注解中的SQL移到映射文件中
<?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类的全类名一致,并且方法名也要一致 -->
    <mapper namespace="com.prim.demo.t_spring_boot_mybatis.mapper.StuMapper">
        <resultMap id="BaseResultMap" type="com.prim.demo.t_spring_boot_mybatis.pojo.Stu">
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="age" column="age"/>
        </resultMap>
        <insert id="save" parameterType="com.prim.demo.t_spring_boot_mybatis.pojo.Stu">
            insert into stu(name, age)
            values (#{name}, #{age})
        </insert>
        <update id="update" parameterType="com.prim.demo.t_spring_boot_mybatis.pojo.Stu">
            update stu
            set name=#{name},
                age=#{age}
            where id = #{id}
        </update>
        <delete id="delete" parameterType="Integer">
            delete
            from stu
            where id = #{id}
        </delete>
        <select id="selectAll" resultMap="BaseResultMap">
            select *
            from stu
        </select>
        <select id="selectOne" parameterType="Integer" resultMap="BaseResultMap">
            SELECT *
            FROM stu
            WHERE id = #{id}
        </select>
    </mapper>


mybatis-config.xml 配置,主要配置了一些基础的信息,比如类名的简化等,这样在映射文件中的parameterType="java.lang.Integer"不用这样写了 直接写parameterType="Integer"

<?xml version="1.0" encoding="utf-8" ?>
<!-- mybatis 的文档约束 -->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias alias="Integer" type="java.lang.Integer"/>
        <typeAlias alias="Long" type="java.lang.Long"/>
        <typeAlias alias="HashMap" type="java.util.HashMap"/>
        <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap"/>
        <typeAlias alias="ArrayList" type="java.util.ArrayList"/>
        <typeAlias alias="LinkedList" type="java.util.LinkedList"/>
    </typeAliases>
</configuration>

Mapper层的代码方法名只要和映射文件中的id一一对应即可

public interface StuMapper {

    void save(Stu stu);

    void update(Stu stu);


    Stu selectOne(int id);


    List<Stu> selectAll();

    void delete(int id);
}

至于service层和controller层的代码不用修改.

如何选择呢?

一般在项目中,注解方式适合简单快速的项目.xml方式更加适合大型项目方便管理.实际项目中根据实际情况来选择.

代码看这里: