1. 简介
1.1maven仓库:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
1.2持久化
数据持久化:
1.持久化就是将程序的数据持久状态和瞬间状态转化的过程
2.内存:断电即失
3.数据库(jdbc),io文件持久化
为什么需要持久化:
有一些对象需要保存,不能因为内存的断电即失而丢掉
1.3持久层
dao层,service层,controller层:
1.完成持久化工作的代码块
2.界限十分明显
2.第一个mybatis程序
2.1环境搭建
2.1.1搭建数据库
2.1.2新建项目
一.新建maven项目
二.删除src
2.2导入maven依赖
mysql驱动
<dependency>
<!--mysql驱动-->
<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.5.9</version>
</dependency>
junit
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
2.3编写代码
编写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.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8"/> //需要连接的数据库的表
<property name="username" value="root"/> //自己数据库的名称
<property name="password" value="root"/> //自己数据库的密码
</dataSource>
</environment>
</environments>
<mappers>
<!--每一个mapper.xml都需要在mybatis核心配置文件中注册!-->
<mapper resource="com/dao/UserMapper.xml"/>
</mappers>
</configuration>
2.4绑定每一个mapper.xml
<mappers>
<!--每一个mapper.xml都需要在mybatis核心配置文件中注册!-->
<mapper resource="com/dao/UserMapper.xml"/>
</mappers>
2.5测试
2.5.1实体类
package com.ran.pojo;
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
2.5.2接口
public interface UserMapper {
public User select(int uid);
public void save(User user);
public int update(User user);
public void delete(int uid);
}
2.5.3接口实现类
<?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.demo_mybatis.UserMapper">
<!--查询操作-->
<select id="select" resultType="com.example.demo_mybatis.User">
select * from user where uid = #{id}
</select>
<!--插入操作-->
<insert id="save" parameterType="com.example.demo_mybatis.User">
insert into user(username,password,email) values(#{username},#{password},#{email});
</insert>
<!--修改操作-->
<update id="update" parameterType="com.example.demo_mybatis.User">
update user set username = #{username},password = #{password} where uid = #{uid}
</update>
<!--删除操作-->
<delete id="delete" parameterType="java.lang.Integer">
delete from user where uid = #{uid}
</delete>
</mapper>
2.5.4测试类
public class TestDome {
//查询操作
@Test
public void testUser1() throws IOException {
String resource = "mybatis.config.xml";
//加载mybatis的主配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建一个mybatis的工厂类
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取UserMapper的动态代理
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//查询select的查询
User user = mapper.select(4);
System.out.println(user);
//关闭sqlSession
sqlSession.close();
}
//插入操作
@Test
public void testUser2() throws IOException {
//模拟user对象
User user=new User();
user.setUsername("ck");
user.setPassword("123");
user.setEmail("145@qq.com");
//加载mybatis的主配置文件
String resource = "mybatis.config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建一个mybatis的工厂类
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取UserMapper的动态代理
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.save(user);
sqlSession.commit();
sqlSession.close();
}
//修改操作
@Test
public void testUser3() throws IOException {
//加载mybatis的主配置文件
String resource = "mybatis.config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建一个mybatis的工厂类
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行操作
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//模拟user对象
User user=new User();
user.setUid(12);
user.setUsername("kun");
user.setPassword("111");
mapper.update(user);
//mybatis更新操作,提交事务
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
}
//删除操作
@Test
public void testUser4() throws IOException {
//加载mybatis的主配置文件
String resource = "mybatis.config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建一个mybatis的工厂类
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过工厂获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行操作
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.delete(12);
//mybatis更新操作,提交事务
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
}
}
2.5.5资源导出问题: 在build中配置resoure,来防止我们资源导出问题
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
3.编写mybatis工具类
package com.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;
//SqlSessionFactory -->SqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource ="mybatis-config.xml";
//使用mybatis第一步:获取SqlSessionFactory对象
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
// 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
// SqlSession 提供了在数据库执行 SQL 命令所需的所有方法
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(//ture);//值设置为ture可以自动提交事务
}
}
4.CRUD
1.namespace
namespace中的包名要和Dao/mapper接口的包名一致!
mybatis获取参数值的两种方式:${}和#{}
${}本质字符串拼接(注意单引号问题)
#{}本质占位符赋值
2.select
选择,查询语句:
1.id:就是对应的namespace中的方法名
2.resultType:sql语句执行的返回值!
3.parameType:参数类型
1.1编写接口
//查询所以用户
List<User> getUserList();
//根据id查询用户
User getUserById(int id);
//增加一个用户
1.2编写对应的mapper中的sql语句
<!--查询语句-->
<select id="getUserList" resultType="com.pojo.User">
select * from users
</select>
<select id="getUserById" resultType="com.pojo.User" parameterType="int">
select * from users where id=#{id}
</select>
1.3测试
@Test
public void Test(){
//第一步获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper 第二部执行sql
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
for (User u:userList
) {
System.out.println(u);
}
//关闭sqlSession
sqlSession.close();
}
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = mapper.getUserById(2);
System.out.println(user);
//关闭sqlSession
sqlSession.close();
}
3.insert
<!--对象中的属性,可以直接取出来-->
<insert id="addUser" parameterType="com.pojo.User">
insert into users (id,name,pwd) value (#{id},#{name},#{pwd})
</insert>
4.update
<!-- 修改用户-->
<update id="updateUser" parameterType="com.pojo.User">
update users set name=#{name},pwd=#{pwd} where id=#{id}
</update>
5.delete
<!-- 删除用户-->
<delete id="deleteUser" parameterType="int" >
delete from users where id=#{id}
</delete>
6:重点:增删改需要提交事物
// 提交事务
sqlSession.commit();
7:map:
map传递参数,直接在sql中取出key
假如,我们的实体类,或者数据库的表,字段或者参数过多,我们应当考虑适应map!
接口:
//map
int addUser2(Map<String,Object> map);
接口实现类:
<!-- map-->
<insert id="addUser2" parameterType="map">
insert into users (id,name,pwd) value (#{userid},#{username},#{userpassword})
</insert>
测试类:
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
HashMap<String, Object> map = new HashMap<>();
map.put("userid",5);
map.put("username","rj");
map.put("userpassword","123435425");
int i = mapper.addUser2(map);if(i>0){
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
//提交事务
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
}
模糊查询:使用通配符 %
<select id="getUserLike" resultType="com.pojo.User">
select * from users where name like #{value}
</select>
<select id="getUserLike" resultType="com.pojo.User">
select * from users where name like "%" #{value} "%"
</select>
@Test
public void getUserLike(){
// 第一步获得sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 方式一:getMapper 第二部执行sql
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserLike("%李%");
for (User u:userList
) {
System.out.println(u);
}
//关闭sqlSession
sqlSession.close();
}
5.配置解析
1.核心配置文件
configuration(配置)
properties(属性 ,如数据库的配置jdbc.properties, 系统参数配置 system.properties)
settings(设置)
typeAliases(设置某个类型的别名 属性:type:设置需要设置别名的类型 alias:别名,若不设置属性,那么该类型拥有默认的别名,即类名且不区分大小写)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器,引入映射文件)
2.环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中
<environments default="development"></environments>
3 .事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
- JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
- MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为
4.数据源(dataSource)
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
- 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。
有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:
driver– 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。url– 这是数据库的 JDBC URL 地址。username– 登录数据库的用户名。password– 登录数据库的密码。defaultTransactionIsolationLevel– 默认的连接事务隔离级别。defaultNetworkTimeout– 等待数据库操作完成的默认网络超时时间(单位:毫秒)。查看java.sql.Connection#setNetworkTimeout()的 API 文档以获取更多信息。
作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”前缀即可,例如:
driver.encoding=UTF8
这将通过 DriverManager.getConnection(url, driverProperties) 方法传递值为 UTF8 的 encoding 属性给数据库驱动。
POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
除了上述提到 UNPOOLED 下的属性外,还有更多属性用来配置 POOLED 的数据源:
poolMaximumActiveConnections– 在任意时间可存在的活动(正在使用)连接数量,默认值:10poolMaximumIdleConnections– 任意时间可能存在的空闲连接数。poolMaximumCheckoutTime– 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)poolTimeToWait– 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000 毫秒(即 20 秒)。poolMaximumLocalBadConnectionTolerance– 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过poolMaximumIdleConnections与poolMaximumLocalBadConnectionTolerance之和。 默认值:3(新增于 3.4.5)poolPingQuery– 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动出错时返回恰当的错误消息。poolPingEnabled– 是否启用侦测查询。若开启,需要设置poolPingQuery属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。poolPingConnectionsNotUsedFor– 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。
JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。这种数据源配置只需要两个属性:
initial_context– 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么将会直接从 InitialContext 中寻找 data_source 属性。data_source– 这是引用数据源实例位置的上下文路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。
和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给 InitialContext。比如:
env.encoding=UTF8
这就会在 InitialContext 实例化时往它的构造方法传递值为 UTF8 的 encoding 属性。
5.属性(properties)
使用properties属性来实现引用配置文件
编写一个配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8
username=root
password=root
6.类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写
<!-- 可以给实体类取别名-->
<typeAliases>
<typeAlias type="com.pojo.User" alias="User"/>
</typeAliases>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
扫描实体类的包,他的默认别名就是这个类的类名,首字母小写
<typeAliases>
<package name="com.pojo"/> <!-- user-->
</typeAliases>
使用注解@Alias("xxx")不默认小写
@Alias("xxx")
public class User {
}
7.设置(settings)
8.映射器(mappers)
注册绑定我们的Mapper文件
第一种方式:
<mappers>
<!--每一个mapper.xml都需要在mybatis核心配置文件中注册!-->
<mapper resource="com/dao/UserMapper.xml"/>
</mappers>
第二种方式:使用class文件绑定注册
<mappers>
<mapper class="com.dao.UserMapper"></mapper>
</mappers>
注意点:
接口和mapper配置文件必须同名!
接口和mapper配置文件必须在同一个包下!
第三种方式:package:使用扫描包进行注入绑定
<mappers>
<package name="com.dao"/>
</mappers>
注意点:
接口和mapper配置文件必须同名!
接口和mapper配置文件必须在同一个包下!
9.resultMap
结果集映射
sql:id name pwd
实体类:id name password
<!-- 结果集映射-->
<resultMap id="UserMap" type="User">
<!--column:数据库中的字段 property:实体类中的属性 -->
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" resultMap="UserMap">
select * from users where id=#{id}
</select>
6.日志
6.1日志工厂
如果数据库操作异常,我们需要排错,日志是最好的助手!
-
SLF4J
-
LOG4J(deprecated since 3.5.9)【掌握】
-
LOG4J2
-
JDK_LOGGING
-
COMMONS_LOGGING
-
STDOUT_LOGGING 【掌握】
-
NO_LOGGING
在mybatis中具体使用哪一个日志实现,在设置中设定!
STDOUT_LOGGING 标准日志输出
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
LOG4J(deprecated since 3.5.9)【掌握】
1.先导包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
2:log4j. properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/ran.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
3:配置log4j为日志的实现
<settings>
<!--标准日志工厂实现-->
<setting name="logImpl" value="LOG4J"/>
</settings>
@Slf4j
public class MyTest01 { }
4:log4j的使用
1.在要使用时Log4j的类中,导入包import org.apache.log4j.Logger;
2.日志对象,参数为当前类的class
static Logger logger = Logger.getLogger(UserDaoTest.class);
3.测试
@Test
public void testLog4j(){
logger.info("info进入testLog4j");
logger.debug("debug进入testLog4j");
logger.error("error进入testLog4j");
}
7:分页
7.1使用limit分页
limit index, pagesize
index:当前页的起始索引
pagesize :每页显示的条数
pageNMum:当前页的页码
index=(pageNum-1 )*pagesize家
select * from users limit 0,2;
使用maybatis分页,核心sql
1接口
List<User> getByLimit(Map<String,Integer> map);
2mapper.xml
<!-- 分页-->
<select id="getByLimit" parameterType="map" resultMap="UserMap">
select * from users limit #{startIndex},#{pageSize}
</select>
3.测试
@Test
public void getByLimit(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Integer> map = new HashMap<>();
map.put("startIndex",0);
map.put("pageSize",2);
List<User> byLimit = mapper.getByLimit(map);
for (User S: byLimit
) {
System.out.println(S);
}
sqlSession.close();
}
7.2 RowBounds分页 :不再使用sql实现
1,接口
// 分页2
List<User> getByRowBounds() ;
2,mapper.xml
<!-- 分页2-->
<select id="getByRowBounds" resultMap="UserMap">
select * from users
</select>
3.测试
@Test
public void getByRowBounds(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 通过RowBounds实现
RowBounds bounds = new RowBounds(1,2);
// 通过java代码层面实现分页
List<User> objects = sqlSession.selectList("com.dao.UserMapper.getByRowBounds",null,bounds);
for (User u:objects
) {
System.out.println(u);
}
sqlSession.close();
}
8.使用注解开发
1.注解在接口上实现
@Select("select * from users")
List<User> getUsers();
2.需要在核心配置文件中绑定接口【重点】
<!-- 绑定接口-->
<mappers>
<mapper class="com.dao.UserMapper"/>
<!-- <mapper resource="com/dao/*Mapper.xml"/> --> 通配注册该路径下所以的xml
</mappers>
本质:反射机制实现
@Select("select * from users where id =#{id}")
User getUserById(@Param("id") int id);//多个参数需要使用@Param("id"),来指定
3.关于@Param( )注解
-
本类型的参数或者String类型,需要加上
-
用类型不需要加
-
如果基本类型的话,可以忽略,但是建议加上
-
我们在sql中引用的就是我们这里的@Param(" ")中设定的值!
9.Lombok
使用步骤
1.在idea中安装Lombok插件!
2.在项目中导入Lombok的jar
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
3
Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
10:多对一处理
多对一:关联
一对多:集合
10.1、按照查询嵌套处理
<!--
思路:
1.查询全部学生信息
2.根据查询出来的学生tid,寻找到对应的老师 ,子查询
-->
<select id="getStudent" resultMap="studentTeacher">
select * from student
</select>
<!--property:实体类中的属性 column:数据库中的字段-->
<resultMap id="studentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性,我们需要单独处理 对象:association 集合:collection-->
<!--property需要处理的多对一的属性,javaType属性的类型-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeachers"/>
</resultMap>
<select id="getTeachers" resultType="Teacher">
select * from teacher where id =#{id}
</select>
10.2、按照结果嵌套处理
<!--按照结果嵌套处理-->
<select id="getStudent2" resultMap="studentTeacher2">
SELECT s.id as sid,s.name as sname,t.id as tid,t.name as tname from student as s,teacher as t;
</select>
<resultMap id="studentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
<result property="id" column="tid"/>
</association>
</resultMap>
10.3实体类
@Data
public class Student {
private int id;
private String name;
//学生需要关联老师
private Teacher teacher;
}
@Data
public class Teacher {
private int id;
private String name;
}
11一对多
11.1、实体类
@Data
public class Student {
private int id;
private String name;
private int tid;
}
@Data
public class Teacher {
private int id;
private String name;
//一个老师关联多个学生
private List<Student> students
}
12.动态sql
if、
接口
List<Person> getPerson(Map map);
<mapper namespace="com.dao.PersonMapper">
<select id="getPerson" parameterType="map" resultType="Person">
select * from person
<where>
<if test="age != null ">
age = #{age}
</if>
<if test="id != null">
and id = #{id}
</if>
</where>
</select>
</mapper>
测试类
@Test
public void test02(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
HashMap hashMap = new HashMap();
hashMap.put("age",17);
hashMap.put("id",1);
List<Person> person = mapper.getPerson(hashMap);
for (Person p:person
) {
System.out.println(p);
}
sqlSession.close();
}
choose、when、otherwise、
<select id="getPerson" parameterType="map" resultType="Person">
select * from person
<where>
<choose>
<when test="age != null">
age = #{age}
</when>
<when test="id != null">
and id = #{id}
</when>
<otherwise>
AND name = #{name} <!--必须写入的值-->
</otherwise>
</choose>
</where>
set、可以取消sql语句update中的逗号!
foreach:
mapper:
List<Person> getPersonId(Map map);
mapper.xml
<!-- select * from person where 1=1 and(id =1 or id=2 or id=3)-->
<select id="getPersonId" resultType="person" parameterType="map">
select * from person
<where>
<foreach collection="ids" item="id" open="and (" separator="or" close=")">
id =#{id}
</foreach>
</where>
</select>
测试类
SqlSession sqlSession = MybatisUtils.getSqlSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
HashMap hashMap = new HashMap();
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
hashMap.put("ids",ids);
List<Person> personId = mapper.getPersonId(hashMap);
for (Person p:personId
) {
System.out.println(p);
}
sqlSession.close();
}
13:缓存
一级缓存、在sqlsession的创建与关闭之间
二级缓存、
<setting name="cacheEnabled" value="true"/>
在当前mapper使用二级缓存
<cache/>
自定义缓存:ehcache
导入依赖
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="true" monitoring="autodetect" dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<!--
name:Cache的唯一标识
maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大
eternal:Element是否永久有效,一但设置了,timeout将不起作用
overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间
和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大
diskPersistent:是否缓存虚拟机重启期数据
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)
-->
<defaultCache maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU" />
<cache name="testCache"
eternal="false"
maxElementsInMemory="100"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
序列化:实现接口
implements Serializable
case when语法
@MapKey
@MapKey("id")
@ResultMap("BaseResultMap")
@Select("select * from user where hotel_address = #{address};")
Map<Long, User> getUserByAddress(@Param("address") String address);
14.通用mapper
14.1、简单查询
package Test01;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInterceptor;
import com.pojo.User;
import com.pojo.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.junit.Before;
import org.junit.Test;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Config;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import java.util.List;
@Slf4j
public class MyTest01 {
private SqlSession session;
@Before
public void before(){
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8");
dataSource.setUsername("root");
dataSource.setPassword("root");
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
//配置mapper位置
configuration.addMapper(UserMapper.class);
//配置分页功能
configuration.addInterceptor(new PageInterceptor());
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
//从刚刚创建的 sqlSessionFactory 中获取 session
session = sqlSessionFactory.openSession();
//创建一个MapperHelper
MapperHelper mapperHelper = new MapperHelper();
//特殊配置
Config config = new Config();
//主键自增回写方法,默认值MYSQL,详细说明请看文档
config.setIDENTITY("MYSQL");
//支持getter和setter方法上的注解
config.setEnableMethodAnnotation(true);
//设置 insert 和 update 中,是否判断字符串类型!=''
config.setNotEmpty(true);
//校验Example中的类型和最终调用时Mapper的泛型是否一致
config.setCheckExampleEntityClass(true);
//启用简单类型
config.setUseSimpleType(true);
//枚举按简单类型处理
config.setEnumAsSimpleType(true);
//自动处理关键字 - mysql
config.setWrapKeyword("`{0}`");
//设置配置
mapperHelper.setConfig(config);
//注册通用接口,和其他集成方式中的 mappers 参数作用相同
//4.0 之后的版本,如果类似 Mapper.class 这样的基础接口带有 @RegisterMapper 注解,就不必在这里注册
mapperHelper.registerMapper(Mapper.class);
//配置 mapperHelper 后,执行下面的操作
mapperHelper.processConfiguration(session.getConfiguration());
}
@Test
public void test01(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setId(1);
User user1 = mapper.selectOne(user);
log.info(user1.toString());
}
@Test
public void test00(){
UserMapper mapper = session.getMapper(UserMapper.class);
PageHelper.startPage(1,2);//分页实现
List<User> users = mapper.selectAll();
for(User user:users){
log.info(user.toString());
}
}
@Test
public void test02(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
int i = mapper.selectCount(user);
System.out.println(i);
}
@Test
public void test03(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setId(1);
User user1 = mapper.selectByPrimaryKey(user);
log.info(user1.toString());
}
@Test
public void test04(){
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setId(1);
List<User> select = mapper.select(user);
// SELECT id,`name`,pwd,udate,email FROM users
log.info(select.toString());
}
}
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.0</version>
</dependency>
14.2、复杂条件查询
@Test
public void test03(){
SqlSession sqlSession = MyUtils.getSqlSession();
// SELECT * from users WHERE (id = 2 OR pwd = "adf") and (name LIKE "李%")
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("id", 2);
criteria.orEqualTo("pwd", "adf");
Example.Criteria criteria1 = example.createCriteria();
criteria1.andLike("name", "李%");
example.or(criteria1);
List<User> select = mapper.selectByExample(example);
for (User u:select
) {
log.info(u.toString());
}
}
14.3、方法介绍
Select
方法:List select(T record);
说明:根据实体中的属性值进行查询,查询条件使用等号
方法:T selectByPrimaryKey(Object key);
说明:根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号
方法:List selectAll();
说明:查询全部结果,select(null)方法能达到同样的效果
方法:T selectOne(T record);
说明:根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号
方法:int selectCount(T record);
说明:根据实体中的属性查询总数,查询条件使用等号
Insert
方法:int insert(T record);
说明:保存一个实体,null的属性也会保存,不会使用数据库默认值
方法:int insertSelective(T record);
说明:保存一个实体,null的属性不会保存,会使用数据库默认值
Update
方法:int updateByPrimaryKey(T record);
说明:根据主键更新实体全部字段,null值会被更新
方法:int updateByPrimaryKeySelective(T record);
说明:根据主键更新属性不为null的值
Delete
方法:int delete(T record);
说明:根据实体属性作为条件进行删除,查询条件使用等号
方法:int deleteByPrimaryKey(Object key);
说明:根据主键字段进行删除,方法参数必须包含完整的主键属性
Example方法
方法:List selectByExample(Object example);
说明:根据Example条件进行查询 重点:这个查询支持通过Example类指定查询列,通过selectProperties方法指定查询列
方法:int selectCountByExample(Object example);
说明:根据Example条件进行查询总数
方法:int updateByExample(@Param("record") T record, @Param("example") Object example); 说明:根据Example条件更新实体record包含的全部属性,null值会被更新
方法:int updateByExampleSelective(@Param("record") T record, @Param("example") Object example);
说明:根据Example条件更新实体record包含的不是null的属性值
方法:int deleteByExample(Object example);
说明:根据Example条件删除数据