Mybatis学习的第二天,有Mybatis核心配置文件、测试的准备、Mybatis工具类的封装、易错点。
Mybatis学习02
1、Mybatis核心配置文件
XML 配置文件中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。
官方推荐XML配置文件命名为:mybatis-config.xml
XML文件放置的路径为:main/resources
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<configuration>
//默认的环境id为“development”
<environments default="development">
//一个环境的配置
<environment id="development">
//事务管理器类型为JDBC,还有一个MANAGED,但是几乎不用了
<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>
</configuration>
2、测试的准备
Jave Bean
实体类的创建和之前的创建方式一样。
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
68
69
70
71
72package com.neversettle.domain;
public class User {
private int id;
private String username;
private String birthday;
private String sex;
private String address;
public User() {
}
public User(int id, String username, String birthday, String sex, String address) {
this.id = id;
this.username = username;
this.birthday = birthday;
this.sex = sex;
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday='" + birthday + '\'' +
", sex=" + sex +
", address='" + address + '\'' +
'}';
}
}实体类的持久化操作,也就是UserDao,但是Mybatis官方使用的是Mapper,所以此处命名为UserMapper(后期优化Mybatis也需要此种规范命名)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package com.neversettle.dao;
import com.neversettle.domain.User;
import java.util.List;
public interface UserMapper {
//获取全部用户信息
List<User> getUserList();
//根据ID获取用户信息
User getUserById(int id);
//新增一个用户
void addUser(User user);
//修改用户信息
int updateUser(User user);
//删除一个用户
int deleteUser(int id);
}这里只需要写出其接口即可,具体的实现是在XML中执行的。
UserMapper的具体实现,需要在其UserMapper的同一目录下建一个名为 UserMapper.xml 文件,文件中写出其具体实现。
官方文档: 事实上 MyBatis 提供的全部特性都可以利用基于 XML 的映射语言来实现,这使得 MyBatis 在过去的数年间得以流行。
XML的基础模板如下:
1
2
3
4
5
6
7
8
9
10
//命名空间应该指向一个具体的接口
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>- mapper中有着CRUD的各个标签,相应的SQL语句都在对应的标签中书写。
- select等标签中id对应的是接口中的方法名,该标签就是接口中方法的具体实现。
- resultType是返回值类型,如返回的类型是具体的实体类,则写出具体的实体类,注意此时需要写出完整的地址,如之前的javabean中实体类的,则需写出实体类所在包名+实体类名,如com.neversettle.domain (后期可使用注解优化)
- 如果需要传参数,则需写出传入的参数类型,向SQL语句中插入时使用 #{} 花括号中写出参数,如果传入的参数是一个实体类,则可以直接写出实体类的属性。如User实体类中有id属性,则可直接写出 #{id} 。
而我实际的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
29
30
31
32
33
<!--namespace绑定一个指定的Dao/Mapper接口-->
<mapper namespace="com.neversettle.dao.UserMapper">
<!-- 查询语句-->
<select id="getUserList" resultType="User">
select * from user
</select>
<!-- 根据ID查询用户-->
<select id="getUserById" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
<!-- 新增加一个用户-->
<insert id="addUser" parameterType="User">
insert into user values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 修改用户信息-->
<update id="updateUser" parameterType="User">
update user set username = #{username} where id = #{id};
</update>
<!-- 删除用户信息-->
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
</mapper>在Test中写测试代码
需要获得类似之前的connection的连接,在Mybatis中是SqlSession,而Mybatis中使用的是工厂模式(还未学习,暂且这样理解),SqlSession是从工厂中获取,而工厂就相当于一个池子,可以产生多个连接,官方给出的工厂获取代码如下:
1
2
3String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);而获取一个SqlSession的代码是:
1
SqlSession sqlSession = sqlSessionFactory.openSession();
接下来就可以来实现接口了,具体应该使用:
1
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
然后便可使用mapper来执行具体的方法,如:
1
User userById = mapper.getUserById(43);
而我的具体代码为(封装了Mybatis获取SqlSession的工具类):
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
68
69
70
71
72package com.neversettle.dao;
import com.neversettle.domain.User;
import com.neversettle.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserMapperTest {
public void test(){
//1.获取SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//2.执行sql(第一种)
UserMapper userDao = sqlSession.getMapper(UserMapper.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user.toString());
}
//3.关闭SqlSession
sqlSession.close();
}
public void getUserById(){
//1.获取sqlsession
SqlSession sqlSession = MybatisUtils.getSqlSession();
//2.执行sql
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.getUserById(43);
System.out.println(userById);
//3.关闭
sqlSession.close();
}
public void addUser(){
//1.获取执行的sqlsession
SqlSession sqlSession = MybatisUtils.getSqlSession();
//2.执行
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.addUser(new User(50,"张三","2020-01-18","男","河北省石家庄市"));
//3.关闭
sqlSession.commit();
sqlSession.close();
}
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.updateUser(new User(50,"123","","",""));
sqlSession.commit();
sqlSession.close();
}
public void deleteUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser(50);
sqlSession.commit();
sqlSession.close();
}
}
3、Mybaits工具类的封装
类似之前的JDBCUtils一样,Mybatis有些步骤也是重复的,所以可以封装成一个工具类:
1 | package com.neversettle.utils; |
4、易错点
首先是UserMapper.xml,每一个mapper都需要在Mybatis的核心配置文件中注册,之前写核心配置文件时没有我们这次使用的Mapper,所以肯定会出现mapper未注册的错误,更改后的Mybatis的核心配置文件:
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
<!--核心配置文件-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=ture&characterEncoding=UTF-8&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="newpassword"/>
</dataSource>
</environment>
</environments>
<!-- 每一个Mapper.xml都需要注册-->
<mappers>
<mapper resource="com/neversettle/dao/UserMapper.xml"/>
</mappers>
</configuration>在执行增删改操作时,都需要提交事务,这和之前学习的不一样,之前学习的还需要自己开启事务然后再提交事务,这里貌似已经自动开启事务了,所以在执行完增删改操作后都需要提交事务,代码为:
1
sqlSession.commit();
第一次运行时,出现了 “ 1 字节的 UTF-8 序列的字节 1 无效” ,这是编码造成的问题,将IDEA的编码改为UTF-8,然后删掉 XML文件,再重写一个即可。