「SpringBoot-DAO」 MyBatis

Posted by Dawn-K's Blog on July 2, 2020

MyBatis

[toc]

介绍

MyBatis 是支持普通 SQL查询, 存储过程和高级映射的优秀持久层框架. MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索. MyBatis 使用简单的 XML或注解用于配置和原始映射, 将接口和 Java 的POJOs(Plain Ordinary Java Objects, 普通的 Java对象)映射成数据库中的记录.

这种普通java对象, 其实就对应着数据库的字段

DAO -> Service -> View pojo会和这三层都有联系

1
2
3
4
5
// Spring 三个注解, 注解是一种标识
@Repository // 标识是一个持久层(数据访问层, 又叫DAO)
@Mapper     // 也是持久层,不过更具体
@Service    // 标识是一个业务层
@Component  // 无法划分层次

目前的理解: 在入口类配置扫描, 单元测试中使用@AutoWaired(这个具体解释很复杂, 涉及到自动装配, 以后再说)之后, 就可以直接获取这个对象, 也就直接可以在单元测试里使用了.

1
2
3
4
5
6
7
@SpringBootApplication
@MapperScan(value="com.neuedu.mapper") // 包扫描
public class HisMain {
    public static void main(String[] args) {
            // something
    }
}

配置

FreeMyBatis

在idea中下载插件FreeMyBatis.

配置pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--jdbc驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>

<!--jdbc 数据源-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<!--mybatis-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>

application.properties

添加mapper的路径

1
2
3
#=classpath*:mapper/**/*.xml
mybatis.mapper-locations=classpath*:/mapper/*.xml
mybatis.type-aliases-package=com.xtsz.entity

增删改查

实际上单表查询一般用 MyBatisPlus, 多表查询才使用 MyBatis.

  1. 新建实体类
  2. 在接口类中配置函数
  3. 在xml中填充sql语句
  4. 在单元测试类中添加语句

实体类

1
2
3
4
5
6
7
8
9
// 实体类 在src/main/java/com.neuedu/entity/User.java
@Data
public class User {
    private Integer id;
    private String username;
    private String birthday;
    private String sex;
    private String address;
}

包扫描

1
2
3
4
5
6
7
8
@SpringBootApplication
@MapperScan(value="com.neuedu.mapper") // 包扫描,也是后续函数生效的关键,如果在配置类中加了就不用再加了.
public class HisMain {
    public static void main(String[] args) {
        // jdbc: select * from users
        SpringApplication.run(HisMain.class, args);
    }
}

接口类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 接口类 在src/main/java/com.neuedu/mapper/UserMapper.java
@Repository
public interface UserMapper {
    List<User> selectAll();

    /**
     * 1. 定义接口方法
     * 2. 编写Mapper.xml
     * 3. 编写测试类进行测试
     * @param user
     * @return
     */
    int insert(User user);

    int update(User user);

    int delete(Integer id);
}

Mapper

首先要安装上文说的FreeMyBatis插件, 否则无法生成. 在上文UserMapper接口类类名(注意, 是类名)上 使用 alt + enter , 就可以弹出框, 其中就有自动生成Mapper的选项, 选中位置之后就可以生成了. 在接口文件移动位置之后, 这个xml也会自动重构 另外接口类函数返回值的变动, 也可以通过alt+enter的方式进行修改 在接口类中的函数, 也可以通过alt+enter的方式在UserMapper.xml中添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 <!--  src/main/resources/mapper/UserMapper.xml -->

 <mapper namespace="com.neuedu.mapper.UserMapper">
    <!--查询记录-->
    <select id="selectAll" resultType="com.neuedu.entity.User">
        select id,username,birthday,sex,address from user
    </select>
    <!--插入记录-->
    <insert id="insert" parameterType="com.neuedu.entity.User">
        insert into user (id,username,birthday,sex,address) values
        (#{id},#{username},#{birthday},#{sex},#{address})
    </insert>

    <update id="update" parameterType="com.neuedu.entity.User">
        update user set username=#{username}, birthday=#{birthday}, sex=#{sex}, address=#{address}
        where id=#{id}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>
</mapper>

单元测试

在类名上 ctrl+shift+T 创建单元测试 在新建的单元测试类上面加入注解@SpringBootTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@SpringBootTest
@Slf4j
class UserMapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    void selectAll() {
        List<User> list = userMapper.selectAll();
        for (User user : list) {
            log.info(user.getUsername() + "\t" + user.getSex() + "\t" + user.getAddress());
        }
//        int size=list.size();
//        Assert.isTrue(list.size()==4);
//        Assert.assertEquals(4,size);
    }

    /**
     * 单元测试方法,返回必须是void ,不能够有任何参数
     * 添加一个@Test注解
     */
    @Test
    public void insert() {
        User user = new User();
        user.setId(5);
        user.setBirthday("2010-01-01");
        user.setSex("女");
        user.setUsername("张三");
        user.setAddress("北京");
        int count = userMapper.insert(user);
    }

    @Test
    public void update() {
        User user = new User();
        user.setId(1);
        user.setBirthday("2011-01-01");
        user.setSex("女");
        user.setUsername("张三");
        user.setAddress("天津");
        int count = userMapper.update(user);
    }

    @Test
    public void delete() {
        userMapper.delete(5);
    }
}

常见错误

expected at least 1 bean which qualifies as autowire candidate for this dependency.

这个就是提示依赖无法注入 一般是入口类忘了加包扫描或者包扫描写错了

数据库某些字段返回值是null

这个是因为在数据库的查询语句中, select后面跟的必须是表中存在的子段, 而返回的必须是实体类中存在的字段, 所以如果二者不一样(指用 * 或者逐个写表中的字段), 就会产生矛盾. 解决方案: 采用as, as前面是数据库字段, as后面是实体类字段. (看来那个说是能把下划线自动替换的也不那么智能呀)

1
2
3
4
<select id="selectAll" resultType="com.neuedu.hosmng.entity.HosMessage">
    select id, const_type_code as "constTypeCode", const_type_name as "constTypeName"
    from hos_message
</select>