学习内容:学习MyBatis框架(Day53)
1、MyBatis框架
2、完整的CRUD操作
1、MyBatis框架
(1)MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架,主要用来封装JDBC操作、利用反射实现实体类与SQL语句之间的相互转换。需要的依赖:mybatis.jar mysql-connector-java.jar 。
ORM:对象关系映射,常见的ORM框架有hibernate、mybatis。
通过SqlSessionFactory来创建SqlSession对象和数据库交互,进行crud(增删改查)操作。Executor是MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护。
mybatis的整体架构如下:
(2)首先创建一个配置文件mybatis-config.xml,配置连接参数,将数据表对应的mapper文件加入到<mappers>节点下。
<?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>
<!--引入db.properties-->
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!--事务管理类型-->
<dataSource type="POOLED">
<property name="username" value="${userName}"/>
<property name="password" value="${password}"/>
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件,即dao层中创建的mapper文件-->
<mappers>
<mapper resource="com/hisoft/dao/UserMapper.xml"/>
<!--可以在硬盘中读取-->
<!--<mapper url="E:\IntelliJ IDEA\WorkSpace\Project01\mybatis\src\main\java\com\hisoft\dao\UserMapper.xml"/>-->
<!--可以引入接口全路径 1.mapper.xml文件名要和接口名一样 2.mapper.xml要和接口类在同一个目录下-->
<!--<mapper class="com.hisoft.dao.UserMapper"/>-->
<!--可以使用扫描包的方式 1.mapper.xml文件名要和接口名一样 2.mapper.xml要和接口类在同一个目录下-->
<!--<package name="com.hisoft.dao"/>-->
</mappers>
</configuration>
(3)创建一个实体类,可以在pom.xml中引入lombok依赖,通过注解给实体类提供get set toString方法,构造方法。使用这个依赖需要下载lombok插件。
<!--给实体类提供get set toString方法,构造方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<!--依赖的范围为编译的时候-->
<scope>provided</scope>
</dependency>
User.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data //提供get set方法
@AllArgsConstructor //全参的构造方法
@NoArgsConstructor //无参的构造方法
@ToString //ToString方法
public class User {
private Integer id;
private String username;
private String sex;
}
(4)在dao层创建UserMapper接口和UserMapper.xml文件
UserMapper接口
public interface UserMapper {
List<User> getAllUsers();
}
UserMapper.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="com.hisoft.dao.UserMapper">
<!--id为创建接口中的方法名,resultType是返回的结果集-->
<select id="getAllUsers" resultType="com.hisoft.pojo.User">
select select id,user_name as userName,sex from tb_user from tb_user
</select>
</mapper>
(5)在pom.xml中进行配置,可以读取到所有的xml文件,因为mapper.xml文件是创建在java目录下的dao目录下的,在mybatis-config.xml文件用<mapper>和<package>标签不能引入到。如果把mapper.xml文件创建在resources目录下,就不需要配置,可以通过文件名直接引入到。
<build>
<resources>
<!--读取到所有的xml文件-->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
(5)连接测试
public class MybatisTest {
public static void main(String[] args) throws IOException {
//获取mybatis配置文件
String resource = "mybatis-config.xml";
//将配置文件读取为输入流
InputStream inputStream = Resources.getResourceAsStream(resource);
//从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//打开sqlSession,通过sqlSession对象进行增删改查
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("com.hisoft.dao.UserMapper.getAllUsers");
sqlSession.close();
//forEach是属于java集合的一个方法,用来遍历集合中的所有内容
users.forEach(System.out::println);
}
}
(6)mybatis添加日志支持
首先添加依赖log4j.jar
在mybatis-config.xml文件进行配置
<settings>
<!--使用log4j做日志管理-->
<setting name="logImpl" value="LOG4J"/>
</settings>
创建log4j.properties配置文件
# 全局日志配置
log4j.rootLogger=ERROR, stdout
# MyBatis 日志配置 路径是UserMapper所在的包
log4j.logger.com.hisoft.dao.UserMapper=TRACE
# 输出位置:控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#指定输出的格式
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#定义输出的格式
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
(7)开启驼峰匹配:从经典数据库的命名规则user_name,到经典java命名规则的映射userName。这样在进行查询等操作时,sql语句可以直接写为select * from tb_user,不用担心实体类属性名和数据库字段名不一致。
在mybatis-config.xml文件中配置
<settings>
<!--开启驼峰匹配-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
(8)给pojo类起一个简称,在mapper.xml中使用时可以直接写简称
在mybatis-config.xml文件中配置
<typeAliases>
<!--type指定类的全路径,alias是简称-->
<!--<typeAlias type="com.hisoft.pojo.User" alias="User"/>-->
<!--把指定包下面的类都起一个简称,默认为类的名字且不区分大小写-->
<package name="com.hisoft.pojo"/>
</typeAliases>
在mapper.xml文件中使用时
<!--resultType返回结果集使用mybatis-config文件中定义的简称User-->
<select id="getAllUsers" resultType="User">
select id,user_name as userName,sex from tb_user
</select>
(9)mybatis中的rs(类型处理器):
StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数等
ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所对应的数据类型
ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
TypeHandler 负责java数据类型和jdbc数据类型(也可以说是数据表列类型)之间的映射和转换
(10)mybatis允许配置多个环境,但是在构建SqlSessionFactory对象时只能选择一个,可以做到很方便的分离多个环境。但是实际使用场景下我们更多使用的是spring管理数据源,做环境的分离。
在mybatis-config.xml文件中配置多个环境
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!--事务管理类型-->
<dataSource type="POOLED">
<property name="username" value="${userName}"/>
<property name="password" value="${password}"/>
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
</dataSource>
</environment>
<environment id="online">
<transactionManager type="JDBC"/> <!--事务管理类型-->
<dataSource type="POOLED">
<property name="username" value="${userName}"/>
<property name="password" value="${password}"/>
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
</dataSource>
</environment>
</environments>
在测试类中构建SqlSessionFactory对象时选择online环境
public class MybatisTest {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//传入的第二个参数是构建SqlSessionFactory对象时选择的环境,不设置默认参数会选择默认环境
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"online");
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("com.hisoft.dao.UserMapper.getAllUsers");
sqlSession.close();
users.forEach(System.out::println);
}
}
2、完整的CRUD操作
(1)完整的CRUD操作,可以下载一个Free Mybatis Plugin插件辅助创建mapper.xml+文件
在dao层创建UserMapper接口
public interface UserMapper {
/**
* 查询所有用户信息
* @return
*/
List<User> getAllUsers();
/**
* 根据id查询用户信息
* @param id
* @return
*/
public User queryUserById(int id);
/**
* 根据id删除用户信息
* @param id
*/
public void deleteUserById(int id);
/**
* 添加用户信息
* @param user
*/
public void addUser(User user);
/**
* 修改用户信息
* @param user
*/
public void updateUser(User user);
}
创建实现类UserMapperImpl.java
public class UserMapperImpl implements UserMapper{
private SqlSession sqlSession;
public UserMapperImpl(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> getAllUsers() {
return sqlSession.selectList("com.hisoft.dao.UserMapper.getAllUsers");
}
@Override
public User queryUserById(int id) {
return sqlSession.selectOne("com.hisoft.dao.UserMapper.getAllUsers",id);
}
@Override
public void deleteUserById(int id) {
sqlSession.delete("com.hisoft.dao.UserMapper.deleteUserById",id);
//需要提交事务才能执行成功
sqlSession.commit();
}
@Override
public void addUser(User user) {
sqlSession.insert("com.hisoft.dao.UserMapper.deleteUserById",user);
//需要提交事务才能执行成功
sqlSession.commit();
}
@Override
public void updateUser(User user) {
sqlSession.update("com.hisoft.dao.UserMapper.updateUser",user);
//需要提交事务才能执行成功
sqlSession.commit();
}
}
在对应的mapper文件中编写sql
<?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="com.hisoft.dao.UserMapper">
<!--id为创建接口中的方法名,resultType是返回的结果集-->
<select id="getAllUsers" resultType="com.hisoft.pojo.User">
select id,user_name as userName,sex from tb_user
</select>
<select id="queryUserById" resultType="com.hisoft.pojo.User">
select id,user_name as userName ,sex from tb_user where id = #{id}
</select>
<!--不用返回结果集-->
<delete id="deleteUserById">
delete from tb_user where id = #{id}
</delete>
<insert id="addUser">
insert into tb_user(user_name,sex) value (#{userName},#{sex})
</insert>
<update id="updateUser">
update tb_user set user_name = #{userName},sex = #{sex} where id = #{id}
</update>
</mapper>
使用junit.jar依赖自动生成测试类,在UserMapper接口右击,选择goto,点击Test自动生成测试类。
public class UserMapperTest {
private SqlSession sqlSession;
private UserMapper userMapper;
@Before //测试之前执行的方法
public void setUp() throws Exception {
//获取mybatis配置文件
String resource = "mybatis-config.xml";
//将配置文件读取为输入流
InputStream inputStream = Resources.getResourceAsStream(resource);
//从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//打开sqlSession,通过sqlSession进行增删改查
sqlSession = sqlSessionFactory.openSession();
userMapper = new UserMapperImpl(sqlSession);
}
@Test //测试方法
public void getAllUsers() {
List<User> users = userMapper.getAllUsers();
users.forEach(System.out::println);
}
@Test
public void queryUserById() {
User user = userMapper.queryUserById(9);
System.out.println("user = " + user);
}
@Test
public void deleteUserById() {
userMapper.deleteUserById(9);
}
@Test
public void addUser() {
User user = new User(9,"段誉","男");
userMapper.addUser(user);
}
@Test
public void updateUser() {
User user = new User(10,"王语嫣","女");
userMapper.updateUser(user);
}
}
(2)动态代理获得mapper实现类:使用动态代理的目标是可以不用书写实现类,只需要书写接口和mapper.xml即可完成crud的操作。
1.mapper.xml文件的根标签<mapper>的namespace 属性值需要和对应的Mapper(dao)接口的全路径一致<mapper namespace="com.hisoft.dao.UserMapper">
2.mapper.xml文件的<select><delete><update><insert>标签的id值要和Mapper(dao)接口的方法名一致<delete id="deleteUserById">
测试类中
@Before //测试之前执行的方法
public void setUp() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
//userMapper = new UserMapperImpl(sqlSession); 不再自定义实现类
//使用动态代理得到实现类对象
userMapper = sqlSession.getMapper(UserMapper.class);
}
此时需要在测试类中提交事务才能完成增删改操作
@Test
public void deleteUserById() {
userMapper.deleteUserById(9);
//需要提交事务才能执行成功
sqlSession.commit();
}