mybatis学习
一、初步认识
1.什么是mybatis?
mybaits是持久层框架,支持自定义SQL、存储过程以及高级映射。
2.为什么使用mybatis?
SQL和代码分离,SQL写在xml文件里
3.JDBC和MYBATIS连接数据库的比较
mybatis提供映射标签,支持对象与数据库的ORM字段映射
JDBC连接和操作数据库在一个java的class文件中完成
传统JDBC | MYBATIS |
---|---|
加载数据库驱动 | mybatis-config.xml文件完成 |
获取数据库链接 | mybatis-config.xml文件完成 |
准备SQL语句 | mapper.xml文件完成 |
预处理SQL语句 | mapper.xml文件完成 |
设置参数 | mapper.xml文件完成 |
执行SQL语句获得结果 | sqlSession完成 |
释放资源 | sqlSession完成 |
数据持久化就是将程序的数据在持久状态和瞬时状态转化的过程。
官网文档:https://mybatis.org/mybatis-3/zh/index.html
二、进阶认识
1.核心配置文件mybatis-config.xml
<!--顶层配置-->
<configuration>
<!--可以在外部引入java配置文件-->
<properties resource="db.properties">
<!--外部配置文件未引入的属性,可以在此配置-->
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
<!--mybatis重要调整设置-->
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
<typeAliases>
<!--方式一、单个类别名设置,文件少时使用-->
<typeAlias type="com.example.pojo.User" alias="User"/>
<!--方式二、设置包名自动扫描,自动识别为类名首字母小写,若想设置为其它,需设置注解,文件多时使用-->
<package name="com.example.pojo"/>
</typeAliases>
<!--多环境配置-->
<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="com/example/dao/userMapper.xml"/>
<!--方式二、通过类名绑定。必须配置文件和接口名一致,并在同一包下(不推荐)-->
<mapper class="com.example.dao.UserMapper"/>
<!--方式三、通过包名扫描。也是必须配置文件和接口名一致,并在同一包下(不推荐)-->
<package name="com.example.dao"/>
</mappers>
</configuration>
2.认识SqlSession
SqlSession是应用程序与持久存储层之间执行交互操作的一个单线程对象。由SqlSession来执行已映射的SQL语句,使用完毕后应关闭。
SqlSession的创建:
SqlSessionFactoryBuilder创建sqlSessionFactory对象,该构造器使用完毕后,就应该丢弃,应放在局部变量里。
sqlSessionFactory为一个线程池,应始终维持一份单例,使用静态单例模式。
SqlSession通过sqlSessionFactory.openSession()创建,执行完毕SQL语句后应立即关闭,不能将实例引用托管给其它作用域。
private static SqlSessionFactory sqlSessionFactory;
static{
try {
//获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//SqlSession完全包含了向数据库执行SQL命令所需的所有方法
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
3.语句映射
映射查询语句select
<!--标签里id关联接口方法,parameterType参数类型(可选),resultType返回结果类型(类限定名,应给出集合内数据类型,不是集合本身)-->
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
<!--select标签中,属性一览-->
<select
id="selectPerson"
parameterType="int"
parameterMap="deprecated"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY"></select>
映射插入,更新,删除
<insert
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20"></insert>
<update
id="updateAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20"></update>
<delete
id="deleteAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20"></delete>
三、安装与配置
1.mybatis源码下载
方式一:使用maven构建(推荐),新建maven项目,将下列依赖代码置于pom.xml文件中
<!--导入依赖-->
<dependencies>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
方式二:在github上下载源码
github下载:https://github.com/mybatis/mybatis-3/
2.编写核心配置文件
在resource目录中新建mybatis-config.xml文件,配置以下代码
<?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?useSSL=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone = GMT"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/example/dao/userMapper.xml"/>
</mappers>
</configuration>
3.编写java工具类将配置文件引入进来,并且获取SqlSession对象
package com.example.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{
try {
//获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//SqlSession完全包含了向数据库执行SQL命令所需的所有方法
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
4.编写JAVA实体类和持久层
在包下新建pojo目录和dao目录,创建映射文件User.Class和UserDao接口
package com.example.pojo;
public class User {
private int id;
private String username;
private String pwd;
public User() {
}
public User(int id, String username, String pwd) {
this.id = id;
this.username = username;
this.pwd = pwd;
}
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 getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
接口文件
package com.example.dao;
import com.example.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getUserList();
}
5.编写mapper配置文件
<?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.example.dao.UserDao">
<select id="getUserList" resultType="com.example.pojo.User">
select * from user
</select>
</mapper>
6.测试调用
public class UserDaoTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
//方式二、直接通过sqlSession进行操作(不推荐,容易拼写错误和需要类型转换)
//List<User> userList = sqlSession.selectList("com.example.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
}
四、异常解决
1.数据库链接不上
可能是驱动版本问题,新版本驱动从com.mysql.jdbc.Driver变为com.mysql.cj.jdbc.Driver
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
也可能是MYSQL断开了链接,未设置时区。解决办法为在URL上添加上serverTimezone = GMT
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone = GMT"/>
五、最佳实践
1.结果集映射
<!--解决列名不一致-->
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
2.动态SQL
以往拼接 SQL 语句很痛苦,mybatis提供了标签用来实现动态SQL功能。
<!--条件判断if,执行所有条件-->
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
<!--选择判断choose、when、otherwise-->
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
<!--where会在存在子语句的时候插入‘where’,并帮助处理AND-->
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
<!--更新语句set,会忽略不在更新的列-->
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
3.缓存
开启二级缓存
<!--开启二级缓存,必须先在核心配置文件中开启-->
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
在Mapper.xml文件中开启缓存
<cache/>
一级缓存默认在SqlSession作用域中,提交或关闭后一级缓存消失,若开启二级缓存,则查询结果保留到二级缓存,供再次查询使用。增删改会影响到二级缓存。缓存仅在一个Mapper文件中生效。