环境
JDK1.8
Mysql5.7
meaven3.6.1
什么是 MyBatis?
MyBatis 是一款优秀的持久层框架
,它支持自定义 SQL、存储过程以及高级映射
。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
中文文档:
mybatis – MyBatis 3 | 简介https://mybatis.org/mybatis-3/zh/index.htmlmeaven仓库
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
环境搭建
搭建数据库
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(40) DEFAULT NULL,
`password` VARCHAR(40) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(id,`name`,`password`)VALUE(1,'张三','123456'),(2,'李四','123456'),(3,'王五','123456');
新建项目
<?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>org.example</groupId>
<artifactId>mybatis-study</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- mysql驱动-->
<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.5.2</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
</project>
创建一个模块
编写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核心配置文件-->
<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=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 每一个Mapper.xml都需要在Mybaits核心配置文件中注册-->
<mappers>
<mapper resource="com/qi/dao/UserMapper.xml"/>
</mappers>
</configuration>
编写mybatis工具类
package com.qi.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 {
//使用mybatis的第一步,获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
// SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
编写代码
实体类
package com.qi.entity;
//实体类
public class User {
private int id;
private String name;
private String password;
public User() {
}
public User(int id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
Dao接口
package com.qi.dao;
import com.qi.entity.User;
import java.util.List;
public interface UserDao {
List<User> getUserList();
}
接口实现类由原来的UserDaoImpl转变成为一个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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.qi.dao.UserDao">
<!-- 查询语句-->
<select id="getUserList" resultType="com.qi.entity.User">
select * from mybatis.user
</select>
</mapper>
测试jutil
org.apache.ibatis.binding.BindingException: Type interface com.qi.dao.UserDao is not known to the MapperRegistry.
MapperRegistry?是什么
meaven资源失效
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
————————————————
版权声明:本文为优快云博主「zerozero121」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_45540125/article/details/115471705
package com.qi.dao;
import com.qi.entity.User;
import com.qi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
//第一步获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//执行SQL 方式一getMapper
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user);
}
//关闭SqlSession
sqlSession.close();
}
}
七步
CRUD
1nameSpace
nameSpace里面的包名要与Dao/Mapper接口包名一致
Mapper
package com.qi.dao;
import com.qi.entity.User;
import java.util.List;
public interface UserMapper {
//获取全部用户
List<User> getUserList();
//根据ID查询用户
User getUserById(int id);
//增加用户
int addUser(User user);
//修改事务
int updateUser(User user);
//删除一个用户
int deleteUser(int id);
}
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.qi.dao.UserMapper">
<!-- 查询语句-->
<select id="getUserList" resultType="com.qi.entity.User">
select * from mybatis.user
</select>
<!-- 实现第二个-->
<select id="getUserById" resultType="com.qi.entity.User" parameterType="int">
select * from mybatis.user where id = #{id}
</select>
<!-- 实现第三个 对象中的属性可以直接取出来-->
<insert id="addUser" parameterType="com.qi.entity.User">
insert into mybatis.user(id,name,password)value (#{id},#{name},#{password});
</insert>
<!-- 实现第四个-->
<update id="updateUser" parameterType="com.qi.entity.User">
update mybatis.user
set name = #{name},password = #{password}
where id = #{id};
</update>
<!-- 实现第五个-->
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
</mapper>
Test
package com.qi.dao;
import com.qi.entity.User;
import com.qi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import javax.jws.soap.SOAPBinding;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
//第一步获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
//执行SQL 方式一getMapper
UserMapper userDao = sqlSession.getMapper(UserMapper.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭SqlSession
sqlSession.close();
}
}
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.getUserById(1);
System.out.println(userById);
sqlSession.close();
}
//增删改需要提交事务
@Test
public void addUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.addUser(new User(4, "爱的看哈", "123456"));
if (res>0){
System.out.println("success");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.updateUser(new User(4,"安静","11111"));
sqlSession.commit();
sqlSession.close();
}
@Test
public void delectUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser(4);
sqlSession.commit();
sqlSession.close();
}
}
Map
//map万能使用
int addUser2(Map<String,Object> map);
<!-- 万能的map查
传递的是map 的key
-->
<insert id="addUser" parameterType="map">
insert into mybatis.user(id,name,password)value (#{userid},#{username},#{passWord});
</insert>
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("userid",7);
map.put("username","阿大赛");
map.put("passWord","713212313");
mapper.addUser2(map);
sqlSession.close();
}
}
配置解析
CRUD
package com.qi.dao;
import com.qi.entity.User;
import java.util.List;
import java.util.Map;
public interface UserMapper {
//模糊查询
List<User> getUserLike(String value);
//获取全部用户
List<User> getUserList();
//根据ID查询用户
User getUserById(int id);
//map万能使用
int addUser2(Map<String,Object> map);
//增加用户
int addUser(User user);
//修改事务
int updateUser(User user);
//删除一个用户
int deleteUser(int id);
}
<?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.qi.dao.UserMapper">
<select id="getUserList" resultType="com.qi.entity.User">
select * from mybatis.user
</select>
<select id="getUserById" resultType="com.qi.entity.User" parameterType="int">
select * from mybatis.user where id = #{id}
</select>
<insert id="addUser" parameterType="com.qi.entity.User">
insert into mybatis.user(id,name,password)values (#{id},#{name},#{password});
</insert>
<update id="updateUser" parameterType="com.qi.entity.User">
update mybatis.user
set name = #{name},password = #{password}
where id = #{id};
</update>
<insert id="addUser2" parameterType="map">
insert into mybatis.user(id,name,password)values (#{userid},#{username},#{passWord});
</insert>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
<select id="getUserLike" resultType="com.qi.entity.User">
select * from mybatis.user where name like #{value}
</select>
</mapper>
package com.qi.dao;
import com.qi.entity.User;
import com.qi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import javax.jws.soap.SOAPBinding;
import java.util.HashMap;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
UserMapper userDao = sqlSession.getMapper(UserMapper.class);
List<User> userList = userDao.getUserList();
for (User user : userList) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
sqlSession.close();
}
}
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.getUserById(1);
System.out.println(userById);
sqlSession.close();
}
@Test
public void addUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.addUser(new User(4, "爱的看哈", "123456"));
if (res>0){
System.out.println("success");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.updateUser(new User(4,"安静","11111"));
sqlSession.commit();
sqlSession.close();
}
@Test
public void delectUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser(4);
sqlSession.commit();
sqlSession.close();
}
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("userid",7);
map.put("username","阿大赛");
map.put("passWord","713212313");
mapper.addUser2(map);
sqlSession.close();
}
@Test
public void getUserLike(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserLike("%李%");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
}
配置解析
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
环境配置(environments)
MyBatis 可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
myBatis默认的事务管理器就是JDBC,连接池POOLED
属性(properties)
我们可以通过Properties属性来实现引用配置文件
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。【db.properties】
1编写一个配置文件
driver= com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=root
2在核心配置文件中引入
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="root"/>
</properties>
1可以直接引入外部文件
2可以在其中增加一些属性配置
3两个文件中有同一个字段优先外部默认
类型别名(typeAliases)
意在降低冗余的全限定类名书写
<typeAliases>
<typeAlias type="com.qi.entity.User" alias="User"/>
</typeAliases>
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean
扫描实体类的包,他的默认别名就为这个类的类名, 首字母小写
<typeAliases>
<!-- <typeAlias type="com.qi.entity.User" alias="User"/>-->
<package name="com.qi.entity"/>
</typeAliases>
实体类少第一种,多就第二种,第一种可以自定义,第二种则需要通过注解自定义
@Alias("hello")
设置
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。
映射器(mappers)
方式二 方式三
作用域(Scope)和生命周期
不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了
局部变量
SqlSessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
局部变量
SqlSessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。想像为数据库连接池
。因此 SqlSessionFactory 的最佳作用域是应用作用域。
最简单的就是使用单例模式或者静态单例模式。
SqlSession
链接到连接池的一个请求
SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
用完关闭
每一个Mapper都代表一个 具体的业务
解决属性名与字段名不一致问题
解决方法其别名
resultMap
结果集映射
id name pwd
id name password
<resultMap id="UserMap" type="User">
<!--column数据库中的元素,property实体类中的字段-->
<result column="id" property="id"></result>
<result column="name" property="name"></result>
<result column="password" property="pwd"></result>
</resultMap>
<select id="getUserById" resultMap="UserMap" >
select * from mybatis.user where id = #{id}
</select>
resultMap
元素是 MyBatis 中最重要最强大的元素。
ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
这就是 ResultMap
的优秀之处——你完全可以不用显式地配置它们
日志
日志工厂
如果数据库出现异常,我们排错,日志就是最好的助手
曾经的 sout debug
现在日志工厂
具体使用日志在设置中设定
STDOUT_LOGGING标准日志输出
在mybatis核心配置文件中,配置我们的日志
Log4j
1导入log4j的包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2log4j的properties文件
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
3配置log4为日志的实现
<settings>
<!-- <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<setting name="logImpl" value="LOG4J"/>
</settings>
4log4j 的使用
简单使用
1,在使用的 Log4j 的类中导包
import org.apache.log4j.Logger;
package com.qi;
import com.qi.dao.UserMapper;
import com.qi.entity.User;
import com.qi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;
public class UserDaoTest {
static Logger logger = Logger.getLogger(UserDaoTest.class);
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.getUserById(1);
System.out.println(userById);
sqlSession.close();
}
@Test
public void testLog4j(){
logger.info("info:进入了testLog4j");
logger.debug("debug:进入了testLog4j");
logger.error("error:进入了testLog4j");
}
}
-----------------------------------------
C:\Users\V556U\.jdks\corretto-1.8.0_302\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=60143:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\plugins\junit\lib\junit5-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\plugins\junit\lib\junit-rt.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\charsets.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\access-bridge-64.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\cldrdata.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\dnsns.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\jaccess.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\jfxrt.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\localedata.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\nashorn.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\sunec.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\sunjce_provider.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\sunmscapi.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\sunpkcs11.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\ext\zipfs.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\jce.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\jfr.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\jfxswt.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\jsse.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\management-agent.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\resources.jar;C:\Users\V556U\.jdks\corretto-1.8.0_302\jre\lib\rt.jar;C:\Users\V556U\Desktop\springboot\mybatis-study\mybatis-03\target\test-classes;C:\Users\V556U\Desktop\springboot\mybatis-study\mybatis-03\target\classes;C:\Users\V556U\.m2\repository\mysql\mysql-connector-java\5.1.47\mysql-connector-java-5.1.47.jar;C:\Users\V556U\.m2\repository\org\mybatis\mybatis\3.5.2\mybatis-3.5.2.jar;C:\Users\V556U\.m2\repository\junit\junit\4.11\junit-4.11.jar;C:\Users\V556U\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\V556U\.m2\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.qi.UserDaoTest,testLog4j
[INFO ] 2021-09-25 09:55:58,932 method:com.qi.UserDaoTest.testLog4j(UserDaoTest.java:31)
info:进入了testLog4j
[DEBUG] 2021-09-25 09:55:58,938 method:com.qi.UserDaoTest.testLog4j(UserDaoTest.java:32)
debug:进入了testLog4j
[ERROR] 2021-09-25 09:55:58,938 method:com.qi.UserDaoTest.testLog4j(UserDaoTest.java:33)
error:进入了testLog4j
Process finished with exit code 0
分页
减少数据的处理量
使用limit分页
语法
select * from user limit startIndex,pageSize;
select * from user limit 2,2;
使用Mybatis实现分页,核心SQL
1接口
List<User> getUserByLimit(Map<String,Integer> map);
2Mapper.XML
<select id="getUserByLimit" parameterType="map" resultType="user">
select * from mybatis.user limit #{startIndex},#{pageSize}
</select>
3测试
@Test
public void getUserByLimit(){
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> userList = mapper.getUserByLimit(map);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
Mybatis分页插件
PageHelpe 可以查看官方的文档进行使用
使用注解开发
使用注解开发
对于像 BlogMapper 这样的映射器类来说,还有另一种方法来完成语句映射。 它们映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置。
本质反射机制
底层:动态代理
CRUD
我们可以在工具类创建时自动提交事务
1openSession设置为true
package com.qi.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 {
//使用mybatis的第一步,获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
// SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
}
2接口加注解
package com.qi.dao;
import com.qi.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
@Select("select * from mybatis.user")
List<User> getUser();
//方法存在多个参数,所有参数前面必须加上注解@Param(“”)注解
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);
@Insert("insert into user(id,name,password) values (#{id},#{name},#{password})")
int addUser(User user);
@Update("update user set name=#{name},password=#{password} where id =#{id}")
int updateUser(User user);
@Delete("delete from user where id =#{id}")
int deleteUser(@Param("id") int id);
}
测试类
【注意我们必须将我们的接口绑定到核心配置文件中】
import com.qi.dao.UserMapper;
import com.qi.entity.User;
import com.qi.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserMapperTest {
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// List<User> userList = mapper.getUser();
//
// for (User user : userList) {
// System.out.println(user);
//
// }
//
// User userById = mapper.getUserById(1);
// System.out.println(userById);
// mapper.addUser(new User(5,"理解啊的啦","211345"));
// mapper.updateUser(new User(5,"ss","214222"));
mapper.deleteUser(5);
sqlSession.close();
}
}
关于@Param()注解
lombok
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
@Data
@AllArgsConstructor
@NoArgsConstructor
多对一
SQl
CREATE TABLE `teacher`(
`id` INT(10) NOT NULL,
`name` VARCHAR(40) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(`id`,`name`) VALUES (1,'杜老师');
CREATE TABLE `student`(
id INT(10) NOT NULL,
`name` VARCHAR(40) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher`(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO student(`id`,`name`,`tid`) VALUES (1,'小明',1);
INSERT INTO student(`id`,`name`,`tid`) VALUES (2,'小红',1);
INSERT INTO student(`id`,`name`,`tid`) VALUES (3,'小张',1);
INSERT INTO student(`id`,`name`,`tid`) VALUES (4,'小李',1);
INSERT INTO student(`id`,`name`,`tid`) VALUES (5,'小王',1);
环境搭建
1导入lombok
2新建实体类Teacher Student
3建立Mapper接口
4建立Mapper.xml文件
5在核心配置文件中绑定注册我们的Mapper接口或者文件
6测试查询是否能够成功
按照查询嵌套处理
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qi.dao.StudentMapper">
<select id="getStudent" resultMap="StudentTeacher">
select * from student;
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
<!-- <collection property=""/>-->
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id};
</select>
</mapper>
按照结果嵌套处理
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname
from student s,teacher t
where s.tid = t.id;
</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"/>
</association>
</resultMap>
一对多
一个老师对应多个学生
对于老师而言就是一对多的关系
package com.qi.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
//关联一个老师
private int tid;
}
package com.qi.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
//一个老师多个学生
private List<Student> students;
}
按照结果嵌套处理
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid,s.name sanme,t.name tname,t.id tid
from student s,teacher t
where s.tid = t.id and t.id = #{tid};
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
按照查询嵌套处理
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from mybatis.teacher where id = #{tid};
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<result property="id" column="id"/>
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from student where tid =#{tid}
</select>
动态SQL
什么动态SQL,不同的需求不同的sql
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
搭建环境
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`author` VARCHAR(100) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8
创建一个基础工程
package com.qi.entity;
import lombok.Data;
import java.util.Date;
@Data
public class Blog {
private int id;
private String title;
private String author;
private Date createTime;
private int views;
}
IF
<select id="queryBlogIF" parameterType="Blog" resultType="blog">
select * from mybatis.blog where 1=1
<if test="title != null">
and title =#{title}
</if>
<if test="author != NULL">
and author = #{author}
</if>
</select>
choose (when, otherwise)
trim (where, set)
<select id="queryBlogIF" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<if test="title != null">
and title =#{title}
</if>
<if test="author != NULL">
and author = #{author}
</if>
</where>
</select>
<update id="updateBlog" parameterType="map">
update mybatis.blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id =#{id}
</update>
动态sql本质sql ,只是在SQL层面上去执行一个逻辑代码
sql片段
有时候我们会将一些SQL片段提取出来
1将固定的用sql抽取出来
2使用的地方用include调用
<sql id="if-title-author">
<if test="title != null">
and title =#{title}
</if>
<if test="author != NULL">
and author = #{author}
</if>
</sql>
<include refid="if-title-author"></include>
Foreach
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id =#{id}
</foreach>
</where>
</select>
缓存
1查询 链接数据库 耗资源
一次查询的结果暂存在一个可以直接查询到的地方------》内存 :缓存
再次查询出来直接走缓存,不用走数据库
1.开启全局缓存
<setting name="cacheEnabled" value="true"/>
2在要使用二级缓存Mapper中开启
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
自定义缓存-ehcache
要在程序中使用
1导包
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
定义
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
ehcache。xml的创建
xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="C:\Users\V556U\Desktop\springboot"/>
<defaultCache
maxElementsInMemory="1"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<!--
属性说明:
l diskStore:当内存中不够存储时,存储到指定数据在磁盘中的存储位置。
l defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
以下属性是必须的:
l maxElementsInMemory - 在内存中缓存的element的最大数目
l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
-->
mybatis流程图