Please enable Javascript to view the contents

Mybatis 快速入门

 ·  ☕ 7 分钟

为Mybatis创建Gradle项目

使用idea创建gradle项目

项目结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   ├── java
    │   └── resources
    └── test
        ├── java
        └── resources

9 directories, 6 files

编写build.gradle

 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
plugins {
    id 'java'
}

group 'io.github.qinry'
version '1.0-SNAPSHOT'

jar {
    archivesBaseName = 'mybatis-sample'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.mybatis:mybatis:3.5.7'
    runtimeOnly 'mysql:mysql-connector-java:8.0.27'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}

test {
    useJUnitPlatform()
}

添加依赖org.mybatis:mybatis:3.5.7mysql:mysql-connector-java:8.0.27,mybatis编译和运行都使用,作用域设置为implement,mysql-connector-java在运行时有效设置为runtimeOnly。设置打包的jar的文档基名为mybatis-sample

编写settings.gradle

1
rootProject.name = 'mybatis-sample'

根项目名为 mybatis-sample,如果有子项目,要使用include后跟子项目的名称,把子项目声明在这里让gradle知道。

Mybatis配置

编写mybatis的xml配置

 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
<?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>
    <properties resource="/db.properties">
    </properties>
     <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false" />
    </settings>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="io/github/qinry/mapper/StudentMapper.xml" />
        <mapper resource="io/github/qinry/mapper/GradeMapper.xml" />
    </mappers>
</configuration>
# src/main/resources/db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
username=springuser
password=123456

配置最重要的两项,分别是environmentmappersenvironment里最重要的是配置transactionMangerdataSource
transactionManager事务管理器一般用JDBCdataSource数据源的类型是Mybatis的POOLED,设置数据源的urlusernamepassword还有drivermappers配置的xml映射文件的位置。

创建数据库表

在mysql建库testdb还有创建两张表。

1
2
3
4
5
6
create table student(
    id bigint not null auto_increment,
    stu_name varchar(32) default null,
    grade_id bigint default null,
    primary key (id)
)engine=innodb  default charset=utf8mb4;
1
2
3
4
5
create table grade(
    id bigint not null auto_increment,
    grade_name varchar(32) default null,
    primary key (id)
)engine=innodb  default charset=utf8mb4;

测试数据:
为grade表插入三条数据

1
2
3
4
insert into grade(grade_name) values
('一年级'),
('二年级'),
('三年级');

为student表插入三条数据

1
2
3
4
insert into student(stu_name, grade_id) values
('王二', 1),
('张三', 2),
('李四', 3);

创建实体pojo

创建Student类

 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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package io.github.qinry.pojo;

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;

    private Long id;
    private String stuName;
    private Long gradeId;

    private Grade grade;

    public Student() {
    }

    public Student(Long id, String stuName, Long gradeId) {
        this.id = id;
        this.stuName = stuName;
        this.gradeId = gradeId;
    }

    public Student(String stuName, Long gradeId) {
        this.stuName = stuName;
        this.gradeId = gradeId;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public Long getGradeId() {
        return gradeId;
    }

    public void setGradeId(Long gradeId) {
        this.gradeId = gradeId;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", stuName='" + stuName + '\'' +
                ", gradeId=" + gradeId +
                ", grade=" + grade +
                '}';
    }
}

Student类属性为id、stuName、gradeId,还有关联属性grade。

创建Grade类

 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
49
50
51
52
53
54
55
56
57
package io.github.qinry.pojo;

import java.util.List;

public class Grade implements Serializable {
    private static final long serialVersionUID = 2L;

    private Long id;
    private String gradeName;

    private List<Student> students;

    public Grade() {
    }

    public Grade(String gradeName) {
        this.gradeName = gradeName;
    }

    public Grade(Long id, String gradeName) {
        this.id = id;
        this.gradeName = gradeName;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getGradeName() {
        return gradeName;
    }

    public void setGradeName(String gradeName) {
        this.gradeName = gradeName;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Grade{" +
                "id=" + id +
                ", gradeName='" + gradeName + '\'' +
                ", students=" + students +
                '}';
    }
}

Grade类的属性id、gradeName,还有关联属性grades。

Student和Grade两表之间关系是一对多。

编写xml映射文件

改写mybatis-config.xml,在environments标签前添加typeAliases标签。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?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>
    ...
    <typeAliases>
        <package name="io.github.qinry.pojo"/>
    </typeAliases>
    <environments default="development">
        ...
    </environments>
    <mappers>
        ...
    </mappers>
</configuration>

在编写xml映射文件时,使用pojo类型时可以直接使用类名(如Student),无须完全限定名(如io.github.qinry.pojo.Student)。

编写StudentMapper.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?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="io.github.qinry.mapper.StudentMapper">
    <cache></cache>

    <sql id="column_list">
        id,stu_name,grade_id
    </sql>
    <select id="findAll" >
        select
        <include refid="column_list" />
        from student
    </select>
</mapper>

编写GradeMapper.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?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="io.github.qinry.mapper.GradeMapper">
    <cache></cache>

    <sql id="column_list">
        id,grade_name
    </sql>
    <select id="findAll" resultType="Grade">
        select
        <include refid="column_list" />
        from grade
    </select>
</mapper>

update、insert、delete的编写类似,就不重复描述。

编写测试

测试StudentMapper

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class StudentMapperTests {
    private SqlSessionFactory sqlSessionFactory;
    @BeforeEach
    void setUp() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis/mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    void findAll() throws IOException {
        try (SqlSession session = sqlSessionFactory.openSession()) {
            List<Student> students = session.selectList("io.github.qinry.mapper.StudentMapper.findAll");
            students.forEach(System.out::println);
        }


    }
}

输出:

1
2
3
Student{id=1, stuName='王二', gradeId=1, grade=null}
Student{id=2, stuName='张三', gradeId=2, grade=null}
Student{id=3, stuName='李四', gradeId=3, grade=null}

测试GradeMapper

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class GradeMapperTests {
    private SqlSessionFactory sqlSessionFactory;
    @BeforeEach
    void setUp() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis/mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    void findAll() throws IOException {
        try (SqlSession session = sqlSessionFactory.openSession()) {
            List<Grade> grades = session.selectList("io.github.qinry.mapper.GradeMapper.findAll");
            grades.forEach(System.out::println);
        }
    }
}

输出:

1
2
3
Grade{id=1, gradeName='一年级', students=null}
Grade{id=2, gradeName='二年级', students=null}
Grade{id=3, gradeName='三年级', students=null}

添加映射器接口

接口名与xml映射文件命名空间一致,方法名与映射文件的与sql相关标签的id一致,比如select标签

添加接口StudentMapper

1
2
3
public interface StudentMapper {
    List<Student> findAll();
}

添加接口与GradeMapper

1
2
3
public interface GradeMapper {
    List<Grade> findAll();
}

修改mybatis-config.xmlmappers标签

1
2
3
<mappers>
    <package name="io.github.qinry.mapper"/>
</mappers>

修改测试用例

1
2
3
4
5
6
7
 @Test
void findAll() throws IOException {
    try (SqlSession session = sqlSessionFactory.openSession()) {
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        mapper.findAll().forEach(System.out::println);
    }
}
1
2
3
4
5
6
7
@Test
void findAll() throws IOException {
    try (SqlSession session = sqlSessionFactory.openSession()) {
        GradeMapper mapper = session.getMapper(GradeMapper.class);
        mapper.findAll().forEach(System.out::println);
    }
}

得到输出结果与未修改一样,不这种方式(getMapper),使用SqlSession相对简洁。

编写高级结果集映射

修改StudentMapper.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<resultMap id="studentResult" type="Student">
    <id property="id" column="stu_id"/>
    <result property="stuName" column="stu_name" />
    <result property="gradeId" column="grade_id"></result>
    <association property="grade" column="grade_id" resultMap="gradeResult"/>
</resultMap>
<resultMap id="gradeResult" type="Grade">
    <id property="id" column="grade_id" />
    <result property="gradeName" column="grade_name" />
</resultMap>
<select id="findAll" resultMap="studentResult">
    select
    s.id as stu_id,
    s.stu_name as stu_name,
    g.id as grade_id,
    g.grade_name as grade_name
    from student s
    left outer join grade g on s.grade_id = g.id
</select>

测试用例输出:

1
2
3
Student{id=1, stuName='王二', gradeId=1, grade=Grade{id=1, gradeName='一年级', students=null}}
Student{id=2, stuName='张三', gradeId=2, grade=Grade{id=2, gradeName='二年级', students=null}}
Student{id=3, stuName='李四', gradeId=3, grade=Grade{id=3, gradeName='三年级', students=null}}

修改GradeMapper.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<resultMap id="gradeResult" type="Grade">
    <id property="id" column="grade_id" />
    <result property="gradeName" column="grade_name" />
    <collection property="students" ofType="Student"  resultMap="studentResult" />
</resultMap>
<resultMap id="studentResult" type="Student">
    <id property="id" column="stu_id" />
    <result property="stuName" column="stu_name" />
</resultMap>
<select id="findAll" resultMap="gradeResult">
    select
    g.id as grade_id,
    g.grade_name as grade_name,
    s.id as stu_id,
    s.stu_name as stu_name
    from grade g
    left outer join student s on g.id = s.grade_id
</select>

测试用例输出:

1
2
3
Grade{id=1, gradeName='一年级', students=[Student{id=1, stuName='王二', gradeId=null, grade=null}]}
Grade{id=2, gradeName='二年级', students=[Student{id=2, stuName='张三', gradeId=null, grade=null}]}
Grade{id=3, gradeName='三年级', students=[Student{id=3, stuName='李四', gradeId=null, grade=null}]}
高级结果集映射,使用级联查询(联表查询),实体必须实现Serializable接口。

了解更多