Mybatis
一、初识mybatis
中文文档:https://mybatis.org/mybatis-3/zh/getting-started.html
(1)Mybatis是一个数据持久层的框架
(2)实现SQL与代码分离
(3)避免了JDBC代码以及手动设置参数和获取结果集
二、第一个Mybatis程序
基本步骤:
0、先导入包 -- 连接数据库的驱动包、Mybatis依赖包、Junit测试包、Lombok
1、获取执行SQL的sqlSession对象(xml配置文件 -> SqlSessionFactory -> SqlSession) -- 封装为一个工具类
https://www.cnblogs.com/yulinfeng/p/6002379.html
2、获取sqlSession对象需要加载mybatis-config.xml配置文件
3、常规操作编写数据类dto|pojo
4、编写mapper(以前的Dao接口)
5、编写对应的mapper.xml(以前的Dao的实现类)
6、编写测试类进行测试
0、先导入包 -- 连接数据库的驱动包、Mybatis依赖包、Junit测试包、Lombok
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ch</groupId>
<artifactId>jdbcstudy</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- 添加连接数据库的驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 添加mybatis依赖包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- 添加测试类Junit测试包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- 简化数据类的get,set等方法,导入lombok依赖包 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
1、获取执行SQL的sqlSession对象(xml配置文件 -> SqlSessionFactory -> SqlSession) -- 封装为一个工具类
package com.ch.util;
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;
/**
* 获取执行SQL的SQLSession对象
*
* 获取的步骤:加载配置文件 -> sqlSessionFactory -> sqlSession
*
* 参照官方文档理解sqlSessionFactoryBuilder、SQLSessionFactory、SQLSession的区别。
*/
public class SqlSessionUtil {
private static SqlSessionFactory ssf;
static {
//1、加载mybatis的配置文件
String resource = "mybatis-config.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
//2、获取sqlSessionFactory对象
ssf = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//3、获取SqlSession对象
public static SqlSession getSqlSession(){
return ssf.openSession();
}
}
2、获取sqlSession对象需要加载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.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mysqlstudy?serverTimezone=GMT&characterEncoding=utf8&useSSL=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 特别注意:每一个mapper.xml都需要在mybatis的核心配置文件中进行注册 -->
<mappers>
<mapper resource="com/ch/mapper/StudentMapper.xml"/>
</mappers>
</configuration>
3、常规操作编写数据类dto|pojo
@Data
public class Student {
private int id;
private int score;
private String name;
}
4、编写mapper(以前的Dao接口)
public interface StudentMapper {
List<Student> getAll();
}
5、编写对应的mapper.xml(以前的Dao的实现类)
namespace:命名空间,一定要和mapper中接口类的包名
id:命名空间下唯一标识,就是对应的方法名
resultType:返回值的类型
parameterType:参数类型
<?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绑定对应的接口 -->
<mapper namespace="com.ch.mapper.StudentMapper">
<!-- id对应接口中的方法名,resultType对应返回值的类型 -->
<select id="getAll" resultType="com.ch.dto.Student">
select * from mysqlstudy.student;
</select>
</mapper>
6、编写测试类进行测试
@Test
public void getAll(){
//获取执行SQL的对象
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
//拿到SQL可以通过接口mapper,或者通过mapper.xml文件
//因为是面向接口开发,所以通过接口mapper获取
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> all = mapper.getAll();
for (Student s : all){
System.out.println(s);
}
}
三、CRUD
特别注意:
增删改需要提交事务
-
可以手动提交:sqlSession.commit();
-
也可以设置为自动提交:在工具类中设置
//3、获取SqlSession对象 public static SqlSession getSqlSession(){ return ssf.openSession(); }
insert
<!-- 增 -->
<insert id="insert" parameterType="com.ch.dto.Student">
insert into student (id, score, name) values (#{id},#{score},#{name});
</insert>
delete
<!-- 删 -->
<delete id="delete" parameterType="_int">
delete from student where id = #{id};
</delete>
select
<!-- 查 -->
<select id="select" resultType="com.ch.dto.Student">
select * from student where id = #{id};
</select>
update
<!-- 改 -->
<update id="update" parameterType="com.ch.dto.Student">
update student set score = #{score},name=#{name} where id = #{id};
</update>
MapperTest
//增
@Test
public void insert(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = new Student();
student.setId(10);
student.setScore(82);
student.setName("喜羊羊");
int insert = mapper.insert(student);
System.out.println(insert > 0 ? "插入成功" : "插入失败");
//增删改一定要提交
sqlSession.commit();
sqlSession.close();
}
//删
@Test
public void delete(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
int delete = mapper.delete(10);
System.out.println(delete > 0 ? "删除成功" : "删除失败");
sqlSession.commit();
sqlSession.close();
}
//查
@Test
public void select(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.select(10);
System.out.println(student);
sqlSession.close();
}
//改
@Test
public void update(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = new Student();
student.setId(10);
student.setScore(82);
student.setName("美羊羊");
mapper.update(student);
sqlSession.commit();
sqlSession.close();
}
Map传值
map可以随意制造参数
(1)多个参数使用Map传值,或者使用注解
(2)如果数据表字段太多,可以考虑使用map
int update2(Map<String,Object> map);
<update id="update2" parameterType="map">
update student set score = #{sc} where id = #{id} and name = #{sname};
</update>
模糊查询
1、直接在传值的使用通配符
List<Student> students = mapper.queryByLike("%小%");
2、可以在SQL中固定死通配符
select * from student where name like "%"#{value}"%";
或
select * from student where `name` like concat('%',#{value},'%');
四、初始配置文件
mybatis-config.xml
事务管理器:JDBC(默认)、MANAGED
数据源类型:UNPOOLED、POOLED(默认)、JNDI
<configuration>
<!-- 官网复制 -->
<!-- environments可以适应多种环境,但是每个SqlSessionFactory只能选择一种环境 -->
<!-- default选择默认环境,对应环境的唯一id -->
<environments default="development">
<environment id="development">
<!-- transactionManager事务管理器,Mybatis中有两种:JDBC和MANAGED -->
<transactionManager type="JDBC"/>
<!-- 数据源【连接数据库】-> dbcp、c3p0、druid -->
<!-- 内置了三种数据源类型:unpooled、pooled、jndi -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mysqlstudy?serverTimezone=GMT&characterEncoding=utf8&useSSL=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 特别注意:每一个mapper.xml都需要在mybatis的核心配置文件中进行注册 -->
<mappers>
<mapper resource="com/ch/mapper/StudentMapper.xml"/>
</mappers>
</configuration>
五、配置优化
0、类型别名
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
1、属性(properties)优化
我们可以使用properties来引入配置文件
*注意问题:
(1)properties的位置
元素类型为 "configuration" 的内容必须匹配"(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"
(2)优先级
如果properties和xml(properties中配置的相关字段)中均使用了同一字段,优先使用外部配置文件
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mysqlstudy?serverTimezone=GMT&characterEncoding=utf8&useSSL=true
username=root
password=root
mybatis-config.xml
<!-- 引入配置文件 -->
<properties resource="db.properties">
<!-- <property name="username" value="root"/> -->
</properties>
2、别名(typeAliases)优化
接口实现类xml中,每个返回值类型或者参数类型,都需要写对应实体类的完整包名,所以使用别名优化
可以有三种方式:(账户以设置别名在配置文件中的位置)
1、固定死,每一个实体类对应一个别名
<typeAliases> <typeAlias type="com.ch.dto.Student" alias="student"></typeAlias> </typeAliases>
2、较灵活,只用设置包即可,使用的是对应包下的每个实体类类名,首字母小写
<typeAliases> <package name="com.ch.dto"/> </typeAliases>
3、最灵活,在所需要的设置的实体类上面添加注解即可
@Data @Alias("student") public class Student { private int id; private int score; private String name; }
3、映射器(Mapper)
使用映射器绑定我们的mapper文件,有3中方式绑定
方式一:直接绑定对应的mapper.xml文件【推荐使用】
<mappers>
<mapper resource="com/ch/mapper/StudentMapper.xml"/>
</mappers>
方式二:使用类class进行绑定
<mappers>
<mapper class="com.ch.mapper.StudentMapper"></mapper>
</mappers>
注意:
- 接口和mapper配置文件必须同名
- 接口和mapper配置文件必须在同一个包下
方式三:使用包映射进行绑定
<mappers>
<package name="com.ch.mapper"/>
</mappers>
注意:
- 接口和mapper配置文件必须同名
- 接口和mapper配置文件必须在同一个包下
六、解决属性和字段不一致
问题描述:实体类中的属性和数据表中的字段名不一致,导致最后查询的结果为null
方式一:
as起别名的方式来进行字段和属性对应
<select id="getAll" resultType="student">
select id, score, name as sName from mysqlstudy.student;
</select>
方式二:【推荐使用】
使用ResultMap进行属性和字段名的映射
<!-- 使用resultMap进行映射,只需映射不一样的字段即可 -->
<resultMap id="st" type="student">
<result column="name" property="sName"></result>
</resultMap>
<select id="getAll" resultMap="st">
select id, score, name as sName from mysqlstudy.student;
</select>
七、Mybatis注解开发
- 适用于简单的SQL语句,复杂的SQL语句推荐使用xml配置文件
- 本质是使用反射来获取注解
- 底层是动态代理
1、在接口上添加注解
@Select("select * from student")
List<Student> getAll1();
2、添加mapper映射(使用类名来进行绑定)
<mappers>
<mapper class="com.ch1.mapper.StudentMapper"></mapper>
</mappers>
CRUD
@Insert("insert into student value(#{id},#{score},#{name})")
int insert1(Student student);
@Delete("delete from student where id = #{id}")
int delete1(@Param("id") int id);
@Select("select * from student where id = #{id}")
Student select1(@Param("id") int id);
@Update("update student set score = #{score} where id = #{id}")
int update1(Student student);