1. MyBatis框架的作用
MyBatis框架的主要作用是简化持久层开发。当使用MyBatis处理数据的增删改查时,只需要定义访问数据的抽象方法,并配置该抽象方法对应的SQL语句即可!
持久层:解决项目中数据持久化处理的组件。
数据持久化:将数据永久的保存下来,即将数据存储在硬盘等可以永久保存数据的存储介质中,如果要将数据保存在这些存储介质中,数据需要以文件的形式存在,通常,可以将数据存到文本文档、XML文档、数据库,通常,在没有明确的说明的情况下,讨论数据持久化指的就是使用数据库存取数据。
内存(RAM,具体表现通常是内存条):是CPU与其它硬件交换数据的“桥梁”,正在执行的程序和数据都在内存中,一旦断电则数据全部丢失。
2. 创建MyBatis项目
创建Maven项目,Group Id为cn.tedu
,Artifact Id为mybatis
,Packaging保持为jar
即可。
然后,在项目中添加相关依赖:
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
| <properties> <java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <mybatis.version>3.5.4</mybatis.version> <mybatis.spring.version>2.0.5</mybatis.spring.version> <spring.version>5.2.7.RELEASE</spring.version> <mysql.version>8.0.12</mysql.version> <druid.version>1.1.23</druid.version> <junit.version>4.13</junit.version> </properties>
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis.spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies>
|
3. 连接数据库
首先,登录MySQL控制台,创建tedu_ums
数据库:
1
| CREATE DATABASE tedu_ums;
|
然后,在项目中,在src/main/resources下创建jdbc.properties文件,用于配置连接数据库的相关信息:
1 2 3 4 5 6
| spring.datasource.url=jdbc:mysql://localhost:3306/tedu_ums?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=root spring.datasource.password=root spring.datasource.initialSize=2 spring.datasource.maxActive=10
|
接下来,在项目的src/main/java下创建cn.tedu.mybatis
包,并在这个包下创建SpringConfig
类,在该类中声明属性以读取以上配置值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package cn.tedu.mybatis;
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource;
@PropertySource("classpath:jdbc.properties") public class SpringConfig { @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.driver-class-name}") private String driverClassName; @Value("${spring.datasource.username}") private String username; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.initialSize}") private Integer initialSize; @Value("${spring.datasource.maxActive}") private Integer maxActive; }
|
然后,继续添加方法,将以上读取到的信息用于配置DataSource
对象,并将该对象交给框架处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Bean public DataSource dataSource() { DruidDataSource ds = new DruidDataSource(); ds.setUrl(url); ds.setDriverClassName(driverClassName); ds.setUsername(username); ds.setPassword(password); ds.setInitialSize(initialSize); ds.setMaxActive(maxActive); return ds; }
|
注意:使用DataSource时,导包必须导javax.sql包中的接口。
接下来,在src/test/java下创建cn.tedu.mybatis
包,并在这个包中创建Tests
测试类,在类中添加测试方法:
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
| package cn.tedu.mybatis;
import java.sql.Connection; import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Tests { @Test public void contextLoads() { System.out.println("Tests.contextLoads()"); } @Test public void getConnection() throws SQLException { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class); DataSource dataSource = ac.getBean("dataSource", DataSource.class); Connection conn = dataSource.getConnection(); System.out.println(conn); ac.close(); }
}
|
如果以上单元测试可以正常通过,则表示连接数据库的相关配置均正确,后续,框架就可以通过以上配置的对象自动连接到数据库。
4. 创建数据表
在tedu_ums
数据库中创建t_user
数据表:
1 2 3 4 5 6 7 8 9
| CREATE TABLE t_user ( id int AUTO_INCREMENT, username varchar(20) NOT NULL UNIQUE, password varchar(20) NOT NULL, age int, phone varchar(20), email varchar(30), PRIMARY KEY (id) ) DEFAULT CHARSET=utf8mb4;
|
5. 插入数据
5.1. 定义抽象方法
当使用MyBatis框架处理增删改查时,抽象方法必须定义在接口中,通常,接口的名称建议使用Mapper
作为最后一个单词。
在cn.tedu.mybatis
包中创建UserMapper
接口,这个接口就专门用于声明访问“用户”数据表中的数据:
1
| public interface UserMapper {}
|
然后,在接口中声明“插入用户数据”的抽象方法,关于抽象方法的声明:
- 【返回值】如果需要执行的数据操作是增、删、改类型的,则使用
Integer
作为返回值类型,表示受影响的行数,其实,也可以使用void
作为返回值类型,表示“不关心受影响的行数”,但是,不建议这么做;如果需要执行的数据操作是查询,则设计为所期望的类型即可,当然,该类型需要能够将查询到的数据封装进去;
- 【方法名称】自定义;
- 【参数列表】根据需要执行的SQL语句中的参数来决定。
当需要执行“插入用户数据”操作时,需要执行的SQL语句大致是:
1
| INSERT INTO t_user (username, password, age, phone, email) VALUES (?,?,?,?,?)
|
可以将以上SQL语句中的参数全部声明到抽象方法的参数列表中,例如:
1
| Integer insert(String username, String password, Integer age, String phone, String email);
|
或者,也可以将SQL语句中的参数全部声明到某个实体类,然后使用实体类作为抽象方法的参数,例如在cn.tedu.mybatis
包下创建User
类:
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
| package cn.tedu.mybatis;
public class User {
private Integer id; private String username; private String password; private Integer age; private String phone; private String email;
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + ", age=" + age + ", phone=" + phone + ", email=" + email + "]"; }
}
|
然后,设计抽象方法为:
1
| Integer insert(User user);
|
目前,MyBatis框架并不知道接口文件的位置,就更加无法使用自定义的抽象方法,必须在配置类的声明之前添加@MapperScan
注解,以指定接口文件所在的包!
5.2. 配置SQL语句
在接口的抽象方法的声明之前,根据需要执行的SQL语句的种类,选择使用@Insert
/ @Delete
/ @Update
/ @Select
这4个当中的某个注解,当前已经添加的抽象方法Integer insert(User user);
需要执行的是INSERT
类型的SQL语句,则需要使用@Insert
注解!
然后,在注解中,配置字符串类型的参数,该参数就是需要执行的SQL语句,在SQL语句中,所有的参数都使用#{}
格式的占位符,在占位符的大括号内是参数User
类的属性名:
1 2
| @Insert("INSERT INTO t_user (username, password, age, phone, email) VALUES (#{username}, #{password}, #{age}, #{phone}, #{email})") Integer insert(User user);
|
最后,还需要在配置类中配置SqlSessionFactoryBean
的对象,为该对象设置数据源,使得MyBatis框架能够自动获取数据库连接,并完成数据访问!所以,在SpringConfig
类中添加:
1 2 3 4 5 6
| @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); return bean; }
|
最后,在src/test/java的cn.tedu.mybatis
包下创建UserMapperTests
测试类,并测试以上方法:
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
| package cn.tedu.mybatis;
import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class UserMapperTests { @Test public void insert() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class); UserMapper userMapper = ac.getBean("userMapper", UserMapper.class); User user = new User(); user.setUsername("spring"); user.setPassword("1234"); user.setAge(26); user.setPhone("1380138000"); user.setEmail("root@baidu.com"); Integer rows = userMapper.insert(user); System.out.println("rows=" + rows); ac.close(); }
}
|
5.3. 获取自动编号的ID值
在抽象方法的上方,补充添加@Options
注解并进行配置,使得可以获取自动编号的ID值,例如:
1 2 3
| @Insert("INSERT INTO t_user (username, password, age, phone, email) VALUES (#{username}, #{password}, #{age}, #{phone}, #{email})") @Options(useGeneratedKeys=true, keyProperty="id") Integer insert(User user);
|
以上在@Options
注解中,配置的useGeneratedKeys=true
表示“需要获取自动生成的值”,keyProperty
表示将获取到的ID值放到参数对象的id
属性中去!
6. 根据id删除用户数据
需要执行的SQL语句大致是:
1
| DELETE FROM t_user WHERE id=?
|
先在UserMapper
接口中添加抽象方法:
1
| Integer deleteById(Integer id);
|
然后,在抽象方法的声明之前添加@Delete
注解来配置SQL语句:
1
| @Delete("DELETE FROM t_user WHERE id=#{id}")
|
最后,编写并执行单元测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Test public void deleteById() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
UserMapper userMapper = ac.getBean("userMapper", UserMapper.class);
Integer id = 1; Integer rows = userMapper.deleteById(id); System.out.println("rows=" + rows);
ac.close(); }
|
7. 将所有用户的密码全部改为某个值
需要执行的SQL语句大致是:
1
| UPDATE t_user SET password=?
|
先在UserMapper
接口中添加抽象方法:
1
| Integer updatePassword(String password);
|
然后,在抽象方法的声明之前添加@Update
注解来配置SQL语句:
1
| @Update("UPDATE t_user SET password=#{password}")
|
最后,编写并执行单元测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| private UserMapper userMapper; private AnnotationConfigApplicationContext ac;
@Before public void doBefore() { ac = new AnnotationConfigApplicationContext(SpringConfig.class); userMapper = ac.getBean("userMapper", UserMapper.class); }
@After public void doAfter() { ac.close(); }
@Test public void updatePassword() { String password = "88888888"; Integer rows = userMapper.updatePassword(password); System.out.println("rows=" + rows); }
|
注意:当单元测试经过以上调整后,每个测试方法中都不用再执行doBefore()
和doAfter()
方法中的代码了,在每次执行@Test
注解的测试方法之前,都会自动调用@Before
注解的方法,并且,在执行@Test
注解的测试方法之后,还会自动调用@After
注解的方法!
8. 统计当前用户表中用户的数量
1 2
| @Select("SELECT COUNT(*) FROM t_user") Integer count();
|
9. 根据id查询某用户的详情
1 2
| @Select("SELECT * FROM t_user WHERE id=#{id}") User findById(Integer id);
|
注意:当查询某1条数据,且没有匹配的查询结果时,将返回null
。
10. 查询所有用户的信息
1 2
| @Select("SELECT * FROM t_user ORDER BY id") List<User> findAll();
|