title: Mybatis学习02
date: 2020-01-19 11:20:05
tags:
Mybatis学习的第二天,有Mybatis核心配置文件、测试的准备、Mybatis工具类的封装、易错点。
XML 配置文件中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。
官方推荐XML配置文件命名为:mybatis-config.xml
XML文件放置的路径为:main/resources
<?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>
//默认的环境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>
Jave Bean
实体类的创建和之前的创建方式一样。
package 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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday='" + birthday + '\'' +
", sex=" + sex +
", address='" + address + '\'' +
'}';
}
}
实体类的持久化操作,也就是UserDao,但是Mybatis官方使用的是Mapper,所以此处命名为UserMapper(后期优化Mybatis也需要此种规范命名)
package 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的基础模板如下:
<?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="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
而我实际的XML应写为(此时使用了注解来代表上方的包名+实体类名):
<?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">
<!--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是从工厂中获取,而工厂就相当于一个池子,可以产生多个连接,官方给出的工厂获取代码如下:
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
而获取一个SqlSession的代码是:
SqlSession sqlSession = sqlSessionFactory.openSession();
接下来就可以来实现接口了,具体应该使用:
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
然后便可使用mapper来执行具体的方法,如:
User userById = mapper.getUserById(43);
而我的具体代码为(封装了Mybatis获取SqlSession的工具类):
package 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 {
@Test
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();
}
@Test
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();
}
@Test
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();
}
@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.updateUser(new User(50,"123","","",""));
sqlSession.commit();
sqlSession.close();
}
@Test
public void deleteUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser(50);
sqlSession.commit();
sqlSession.close();
}
}
类似之前的JDBCUtils一样,Mybatis有些步骤也是重复的,所以可以封装成一个工具类:
package com.neversettle.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
//获取sqlsessionfactory对象
InputStream inputStream = null;
try {
String resource = "mybatis-config.xml";
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
// SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
// 你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
public static SqlSession getSqlSession(){
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
}
}
首先是UserMapper.xml,每一个mapper都需要在Mybatis的核心配置文件中注册,之前写核心配置文件时没有我们这次使用的Mapper,所以肯定会出现mapper未注册的错误,更改后的Mybatis的核心配置文件:
<?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>
<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>
在执行增删改操作时,都需要提交事务,这和之前学习的不一样,之前学习的还需要自己开启事务然后再提交事务,这里貌似已经自动开启事务了,所以在执行完增删改操作后都需要提交事务,代码为:
sqlSession.commit();
第一次运行时,出现了 “ 1 字节的 UTF-8 序列的字节 1 无效” ,这是编码造成的问题,将IDEA的编码改为UTF-8,然后删掉 XML文件,再重写一个即可。
原文:https://www.cnblogs.com/wuren-best/p/12441507.html