MyBatis
1.概述
主流的ORM框架,之前叫做iBatis,后更名为MyBatis(ORM还有一个主流的框架,Hibernate)
-
二者区别
-
MyBatis:半自动ORM框架
框架值提供一部分功能,剩下的要我们手动完成即MyBatis没有提供pojo与数据库表的映射,它只是实现了pojo和SQL之间的映射关系,需要开发者自定义SQL语句,以及数据与pojo之间的装配关系
-
Hibernate:全自动框架
实现类pojo和数据库之间的映射,同时可以自动生成SQL语句,并完成执行
MyBatis虽然没有Hibernate方便,但是这种半自动化的方式提高了框架的灵活性,开发者可以根据具体的业务需求,完成定制化的持久层解决方案
MyBatis是一款优秀的持久框架,它支持自定义sql,存储过程及高级映射,MyBatis简化了几乎所有的JDBC代码,以及设置参数,获取结果集对象的工作。MyBatis可以通过简单的XML配置或注解来配置映射关系。
复习JDBC
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
Connection connection = Drivermanager.getConnection(url,username,password);
//3.定义sql
String sql = "select * from student where id = ?";
//4.预编译
PreparedStatement statement = connection.preparedStatement(sql);
//5.设置参数
statement.setInteger(1,2001);
//6. 执行sql,封装结果
ResultSet result = statement.executeQuery();
**Hibernate框架:**全自动映射ORM框架
2.为什么使用MyBatis
JDBC:
SQL编写在代码中,耦合度比较高
实际开发中SQL会经常被更新,维护不易
Hibernate:
内部自动生成SQL,不方便特殊优化
长难复杂的SQL,对Hibernate处理很不容易
基于全映射的全自动框架,进行字段部分映射比较困难,并且会导致数据库性能下降
MyBatis:
SQL和Java编码分离功能划分清楚,一个专注数据,一个专注业务
核心SQL可以自己编写,优化比较方便
3.MyBatis环境搭建
步骤:
1.创建Maven工程,并导入相关依赖
2.创建实体类
3.创建dao层接口
4.创建MyBatis主配置文件:SQLMapConfig.xml
5.创建映射配置文件UseDao.xml
注意事项:
1.创建Directory和packge的区别
directory:com.wdzl.dao创建的是以及目录
packge:com.wdzl.dao创建了三级目录
2.MyBatis的映射配置文件所在目录层级要与对应的dao层接口目录层级相同
3.映射配置文件mapper标签namespace属性的值必须对应接口的全限定类名
4.映射配置文件selet标签id属性必须与对应接口中的方法名一直,不能随便写
5.只要遵循2,3,4,的规定,我们就不用去写接口的实现类
3.2测试案例
步骤:
1.读取配置文件
2.创建Sqlsessionfactory 对象–>通过SqlSessionFactoryBuilder对象获取
创建工厂使用构建者模式
构建者模式:把复杂的对象构建细节进行隐藏,使得使用者直接调用方法拿到该对象
3.使用工厂对象生产SqlSession对象
生产SqlSession使用了工厂模式
工厂模式:
a.解耦:降低类与类之间的耦合性,因为屏蔽了new关键字
b.便于维护:将对象的创建和使用进行分离,当业务逻辑发生变化时,只需要修改工厂中的代码即可
4.使用SQLSession对象获取接口代理对象
代理模式:不改变源码的情况下对已有的方法进行增强
5.使用代理对象调用方法
6.释放资源
a.入门案例
现在是最复杂的状态,后面学了注解等方法后就不一样了
在pom文件里导入依赖
<dependencies>
<!--测试单元-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<!--MySql连接驱动-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<!--MyBatis-->
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<!--日志解析lo4j-->
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0d6DHO8X-1616916840107)(C:\Users\dell\Pictures\java截图\HelloMyBatis结构截图.png)]
以上是结构截图
- 现在UserDao 里面创建一个List作为入门案例
public interface UserDao {
/**
* 查询所有用户信息
*/
List<Student> findAll();
}
- 再在pojo里根据数据库表创建一个实体类,这里我直接用我的表,但是无参,有参,get,set,toString 我就不写了
/**
* 学生类
*/
public class Student {
private int id;
private String username;
private String gender;
private String birthday;
private String address;
}
- 在resource里面,创建两个数据库的配置文件 的配置文件UserDao.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.wdzl.dao.UserDao"><!--对应dao层接口的权限定类名-->
<select id="findAll" resultType="com.wdzl.pojo.Student">
select * from student;
</select>
</mapper>
- SqlMapConfig.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="mysql">
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/wdzl/dao/UserDao.xml"/>
</mappers>
</configuration>
- test
/**
* UserDao测试类
* @author lp
* @version 1.0
* MyBatis 入门案例测试实现步骤
* 1.读取配置文件
* 2.创建SqlSessionFactory工厂
* 3.用工厂生产SqlSession对象
* 4.使用SqlSessiond对象创建dao层的带对象
* 5.使用代理对象执行方法
* 6.释放资源
*/
public class UserDaoTest {
@Test
public void findAllTest() throws IOException {
//读取配置文件
InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSessiond对象创建dao层的带对象
UserDao userDao = session.getMapper(UserDao.class);
//5.使用代理对象执行方法
List<Student> students = userDao.findAll();
//遍历
for (Student student:students){
System.out.println(student);
}
//释放资源
session.close();
is.close();
}
}
b.入门案例2.0(添加注解)
该案例只是对上面的进行简单的修改
- 首先将xml文件中的标签进行修改,resource->classs&&/->.&&userDao.xml->userDao其中UserDao.xml已经删除(注解会将其替代)
<mappers>
<mapper class="com.wdzl.dao.UserDao"/>
</mappers>
- 在UserDao上直接注解
public interface UserDao {
/**
* 查询所有用户信息
*/
@Select("select * from student;")
List<Student> findAll();
}
-
实体类不变
-
test不变
效果与之前相同
c.关于myBatis的增删改查(crud)(xml方法)
1.在UserDao接口里创建每个需求的接口
public interface UserDao {
/**
* 查询所有用户信息
*/
List<User> findAll();
/**
* 添加用户的方法
* @param user
*/
void addUser(User user);
/**
* 修改用户信息
*/
void updateUser(User user);
/**
* 删除用户
*/
void deleteUser(User user);
}
2.创建User实体类,与数据库表一一对应
get,set,有参无参,toString这些我就不写了
public class User {
private int uid;
private String username;
private String sex;
private String birthday;
private String address;
}
在xml里将这些方法相应的SQL语言都写上(如想完成其他更复杂的操作,只需要类似在xml文件中添加更复杂的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.wdzl.dao.UserDao"><!--对应dao层接口的全限定类名-->
<resultMap id="userMap" type="com.wdzl.pojo.User">
<id property="uid" column="id"></id>
<!--实体类对应--> <!--数据库对应-->
<result property="username" column="username"></result>
</resultMap>
<!--查询所有用户信息的方法-->
<select id="findAll" resultMap="userMap">
select * from user
</select>
<!--添加用户-->
<insert id="addUser" parameterType="com.wdzl.pojo.User">
<selectKey keyProperty="uid" order="AFTER" resultType="int">
select last_insert_id();
</selectKey>
insert into user(username,birthday,sex,address) values (#{
username},#{
birthday},#{
sex},#{
address})
</insert>
<!--修改信息-->
<update id="updateUser" parameterType="com.wdzl.pojo.User">
update user set address=${
address} where username=${
username}
</update>
<!--删除用户-->
<delete id="deleteUser" parameterType="com.wdzl.pojo.User">
delete from user where username=#{
username}
</delete>
</mapper>
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="mysql">
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="200429@wbnb"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/wdzl/dao/UserDao.xml"/>
</mappers>
</configuration>
test
/**
* UserDao测试类
* @author lp
* @version 1.0
* MyBatis入门案例测试实现步骤
* 1. 读取配置文件
* 2.创建SqlSessionFactory工厂
* 3.用工厂生产SqlSession对象
* 4.使用SqlSession对象创建dao层的代理对象
* 5.使用代理对象执行方法
* 6.释放资源
*/
public class UserDaoTest {
InputStream is;
SqlSessionFactoryBuilder builder;
SqlSessionFactory factory;
SqlSession sqlSession;
UserDao userDao;
@Before
public void init() throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession对象创建dao层的代理对象
userDao = sqlSession.getMapper(UserDao.class);
}
@After
public void destroy() throws IOException {
sqlSession.close();
is.close();
}
@Test
public void findAllTest() throws IOException {
List<User> users = userDao.findAll();
for (User user :users) {
System.out.println(user);
}
}
@Test
public void testAddUser() throws IOException {
User user = new User(0, "**", "男", "2000-01-01", "宝鸡");
userDao.addUser(user);
System.out.println(user);
sqlSession.commit();//提交事务
System.out.println("--------------------------");
System.out.println(user);
}
@Test
public void testUpdateUser() {
User user = new User();
user.setUsername("**");
user.setAddress("西安");
userDao.updateUser(user);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
//遍历
for (User user2 :users) {
System.out.println(user2);
}
}
@Test
public void testDeleteUser() {
User user = new User();
user.setUsername("**");
userDao.deleteUser(user);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
//遍历
for (User user2 :users) {
System.out.println(user2);
}
}
}
d.MyBatis多表查询
在MySql中,表与表之间有三种
1.1-1
2.1-多
3.多-多
举例
一对一:公民和身份证号
一对多,多对一:
多个学生对应班级
一个班级有多个学生
多对多:学生和老师
-
特殊
如果将订单取出,这个订单只能属于一个用户,索引在MyBatis 里就把多对一的关系,按照一对一的关系纪念性处理
d.1多表查询crud
-
导包
<dependencies> <!--测试单元--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--Mysql连接驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <!--日志解析lo4j--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
-
建实体类
public class User {
private int id;
private String username;
private String sex;
private String birthday;
private String address;
}
public class QueryVo {
private User user;
private List<Integer> ids;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}
public class Account {
private int id;
private int uid;
private double money;
}
3.创建接口
package com.wdzl.dao;
import com.wdzl.pojo.QueryVo;
import com.wdzl.pojo.User;
import java.util.List;
/**
* 操作学生数据的接口
*/
public interface UserDao {
/**
* 查询所有用户信息
*/
List<User> findAll();
/**
* 根据id查询指定用户信息
*/
User findUserById(int id);
/**
* 模糊查询-根据用户名模糊查询用户信息
*/
List<User> findUserByName(String name);
/**
* 查询用户总记录数
*/
int findTotal();
/**
* 根据给定的条件,对满足条件的用户信息进行符合查询
* 查询满足名称为周杰伦,性别为男的所有用户信息
*/
List<User> findUserByCondictions(User user);
List<User> findUserByIds(QueryVo vo);
}
4.创建userDao配置文件
<?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.wdzl.dao.UserDao"><!--对应dao层接口的全限定类名-->
<sql id="userBase">
select * from user
</sql>
<resultMap id="userMap" type="com.wdzl.pojo.User">
<id property="uid" column="id"></id>
<result property="username" column="username"></result>
</resultMap>
<!--查询所有用户信息的方法-->
<select id="findAll" resultType="user">
<include refid="userBase"></include>
</select>
<!--模糊查询-->
<select id="findUserByName" parameterType="string" resultType="com.wdzl.pojo.User">
select * from user where username like #{
name}
</select>
<!--查询用户总记录数-->
<select id="findTotal" resultType="int">
select count(id) from user
</select>
<!--根据包装类模糊查询用户数据-->
<select id="findUserByVo" parameterType="com.wdzl.pojo.QueryVo" resultType="com.wdzl.pojo.User">
select * from user where username like #{
user.username}
</select>
<!--根据指定信息进行符合条件查询-->
<select id="findUserByCondictions" parameterType="user" resultType="user">
select * from user
<where>
<if test="username!=null">
and username=#{
username}
</if>
<if test="sex!=null">
and sex=#{
sex}
</if>
</where>
</select>
<select id="findUserByIds" parameterType="queryVo" resultType="user">
select * from user
<where>
<if test="ids!=null and ids.size()>0">
<foreach collection=" ids" open="and id in(" close=")" item="id" separator=",">
#{
id}
</foreach>
</if>
</where>
</select>
</mapper>
5.创建总配置文件
<?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>
<typeAliases>
<!-- <typeAlias type="com.wdzl.pojo.User" alias="aa"></typeAlias>-->
<package name="com.wdzl.pojo" />
</typeAliases>
<!-- 配置环境 -->
<environments default="mysql">
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="200429@wbnb"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/wdzl/dao/UserDao.xml"/>
</mappers>
</configuration>
test
package com.wdzl.dao;
import com.wdzl.pojo.QueryVo;
import com.wdzl.pojo.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* UserDao测试类
* @author lp
* @version 1.0
* MyBatis入门案例测试实现步骤
* 1. 读取配置文件
* 2.创建SqlSessionFactory工厂
* 3.用工厂生产SqlSession对象
* 4.使用SqlSession对象创建dao层的代理对象
* 5.使用代理对象执行方法
* 6.释放资源
*/
public class UserDaoTest {
InputStream is;
SqlSessionFactoryBuilder builder;
SqlSessionFactory factory;
SqlSession sqlSession;
UserDao userDao;
@Before
public void init() throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession对象创建dao层的代理对象
userDao = sqlSession.getMapper(UserDao.class);
}
@After
public void destroy() throws IOException {
sqlSession.close();
is.close();
}
@Test
public void findAllTest() throws IOException {
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
//遍历
for (User user :users) {
System.out.println(user);
}
}
@Test
public void testFindUserById() {
User user = userDao.findUserById(9);
System.out.println(user);
}
@Test
public void testFindUserByName() {
List<User> users = userDao.findUserByName("%德%");
for (User user :users) {
System.out.println(user);
}
}
@Test
public void testFindTotal() {
int total = userDao.findTotal();
System.out.println(total);
}
@Test
public void testFindUserByConditions(){
User user = new User();
user.setUsername("周杰伦");
user.setSex("男");
List<User> users = userDao.findUserByCondictions(user);
for (User u:users){
System.out.println(u);
}
}
@Test
public void testFindUserByQueryVo(){
QueryVo vo = new QueryVo();
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
list.add(5);
list.add(7);
list.add(9);
vo.setIds(list);
List<User> users = userDao.findUserByIds(vo);
for (User u:users){
System.out.println(u);
}
}
}
d.2多表查询一对一
假设一个账户对应一个用户,一个用户也对应一个账户
- 导依赖
<?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.wdzl</groupId>
<artifactId>mybatis_manyToOne</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--测试单元-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--Mysql连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--日志解析lo4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
- 创建两个实体类,与SQL表的变量一一对应
package com.wdzl.pojo;
/**
* 账户类
*/
public class Account {
private int aid;
private int uid;
private double money;
private User user;
//一个账户对应一个用户
public Account() {
}
public Account(int aid, int uid, double money, User user) {
this.aid = aid;
this.uid = uid;
this.money = money;
this.user = user;
}
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Account{" +
"aid=" + aid +
", uid=" + uid +
", money=" + money +
", user=" + user +
'}';
}
}
package com.wdzl.pojo;
import java.util.List;
/**
* 用户类
* @author lp
* @version 1.0
*/
public class User {
private int uid;
private String username;
private String sex;
private String birthday;
private String address;
//一个用户可以有多个账户
private List<Account> accounts;
public User() {
}
public User(int uid, String username, String sex, String birthday, String address, List<Account> accounts) {
this.uid = uid;
this.username = username;
this.sex = sex;
this.birthday = birthday;
this.address = address;
this.accounts = accounts;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", username='" + username + '\'' +
", sex='" + sex + '\'' +
", birthday='" + birthday + '\'' +
", address='" + address + '\'' +
", accounts=" + accounts +
'}';
}
}
- 创建接口
/**
* 操作用户实体类的接口
*/
public interface UserDao {
/**
* 查询用户列表
* @return
*/
List<User> findAll();
}
/**
* 操作账户表的接口
*/
public interface AccountDao {
/**
* 查询账户列表
* @return
*/
List<Account> findAll();
}
- 创建接口对应的xml配置文件
- AccountDao.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.wdzl.dao.AccountDao"><!--对应dao层接口的全限定类名-->
<resultMap id="accountUserMap" type="account">
<id property="aid" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!-- 配置一对一关系映射-->
<association property="user" column="uid" javaType="user">
<id property="uid" column="uid"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</association>
</resultMap>
<select id="findAll" resultMap="accountUserMap">
select a.aid,a.money,u.uid,u.username,u.sex,u.address from account a,User u where u.uid = a.uid
</select>
</mapper>
UserDao.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.wdzl.dao.UserDao"><!--对应dao层接口的全限定类名-->
<resultMap id="userAccountMap" type="user">
<id property="uid" column="uid"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<collection property="accounts" ofType="account" column="id">
<id property="aid" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
</collection>
</resultMap>
<select id="findAll" resultMap="userAccountMap">
select * from user u left outer join account a on u.uid = a.uid
</select>
</mapper>
- 创建总配置文件
<?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>
<typeAliases>
<!-- <typeAlias type="com.wdzl.pojo.User" alias="aa"></typeAlias>-->
<package name="com.wdzl.pojo" />
</typeAliases>
<!-- 配置环境 -->
<environments default="mysql">
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis2?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="200429@wbnb"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/wdzl/dao/UserDao.xml"/>
<mapper resource="com/wdzl/dao/AccountDao.xml"/>
</mappers>
</configuration>
- test
package com.wdzl.dao;
import com.wdzl.pojo.Account;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class AccountDaoTest {
InputStream is;
SqlSessionFactory factory;
SqlSession sqlSession;
AccountDao accountDao;
/**
* 初始化
* @throws IOException
*/
@Before
public void init() throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession对象创建dao层的代理对象
accountDao = sqlSession.getMapper(AccountDao.class);
}
/**
* 释放资源
* @throws IOException
*/
@After
public void destroy() throws IOException {
sqlSession.close();
is.close();
}
@Test
public void testFindAll(){
List<Account> accountDaos = accountDao.findAll();
for (Account a: accountDaos){
System.out.println(a);
}
}
}
package com.wdzl.dao;
import com.wdzl.pojo.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* UserDao测试类
* @author lp
* @version 1.0
* MyBatis入门案例测试实现步骤
* 1. 读取配置文件
* 2.创建SqlSessionFactory工厂
* 3.用工厂生产SqlSession对象
* 4.使用SqlSession对象创建dao层的代理对象
* 5.使用代理对象执行方法
* 6.释放资源
*/
public class UserDaoTest {
InputStream is;
SqlSessionFactory factory;
SqlSession sqlSession;
UserDao userDao;
/**
* 初始化
* @throws IOException
*/
@Before
public void init() throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession对象创建dao层的代理对象
userDao = sqlSession.getMapper(UserDao.class);
}
/**
* 释放资源
* @throws IOException
*/
@After
public void destroy() throws IOException {
sqlSession.close();
is.close();
}
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for (User u:users){
System.out.println(u);
}
}
}
SQL中的四张表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C8UK08E5-1616916840108)(C:\Users\dell\Pictures\java截图\Account.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4kAJflUe-1616916840109)(C:\Users\dell\Pictures\java截图\role.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o741phtW-1616916840110)(C:\Users\dell\Pictures\java截图\User.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ASCLmnRu-1616916840111)(C:\Users\dell\Pictures\java截图\user-role.png)]
一对一实现了,多对一自然也实现了
d.3多表查询一对多
与上面类似,不同的是要User实体类上简历一个List集合
//一个用户可以有多个账户
private List<Account> accounts;
为了不造成代码的冗余,这一次我用注解方法来写
- 导入依赖
- 创建实体类(前面一斤刚提到过)
- 建立接口
AccountDao
package com.wdzl.dao;
import com.wdzl.pojo.Account;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
/**
* 操作账户表的接口
*/
public interface AccountDao {
/**
* 查询账户列表
* @return
*/
@Select("select * from account")
@Results(id = "accountMap",value = {
@Result(id = true,column = "aid",property = "aid"),
@Result(column = "uid",property = "uid"),
@Result(column = "money",property = "money"),
@Result(column = "uid",property = "user",one = @One(
select = "com.wdzl.dao.UserDao.findUserByUid",
fetchType = FetchType.EAGER
))
})
List<Account> findAll();
@Select("select *from account where uid=#{uid}")
Account findAccountByUid(Integer uid);
}
UserDao
package com.wdzl.dao;
import com.wdzl.pojo.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
/**
* 操作用户实体类的接口
*/
@CacheNamespace(blocking = true)//开启二级缓存
public interface UserDao {
/**
* 查询用户列表
* @return
*/
@Select("select * from user")
@Results(id = "userMap",value = {
@Result(id = true,column = "uid",property = "uid"),
@Result(column = "username",property = "username"),
@Result(column = "birthday",property = "birthday"),
@Result(column = "sex",property = "sex"),
@Result(column = "address",property = "address"),
@Result(property ="accounts",
column = "uid",
many = @Many(select = "com.wdzl.dao.AccountDao.findAccountByUid",
fetchType = FetchType.LAZY))
})
List<User> findAll();
@Select("select *from user where uid=#{uid}")
User findUserByUid(Integer uid);
}
- 建立总配置文件
<?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>
<typeAliases>
<package name="com.wdzl.pojo" />
</typeAliases>
<!-- 配置环境 -->
<environments default="mysql">
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源-->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis2?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="200429@wbnb"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.wdzl.dao"/>
</mappers>
</configuration>
test
package com.wdzl.dao;
import com.wdzl.pojo.Account;
import com.wdzl.pojo.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* UserDao测试类
* @author lp
* @version 1.0
* MyBatis入门案例测试实现步骤
* 1. 读取配置文件
* 2.创建SqlSessionFactory工厂
* 3.用工厂生产SqlSession对象
* 4.使用SqlSession对象创建dao层的代理对象
* 5.使用代理对象执行方法
* 6.释放资源
*/
public class UserDaoTest {
InputStream is;
SqlSessionFactory factory;
SqlSession sqlSession;
UserDao userDao;
/**
* 初始化
* @throws IOException
*/
@Before
public void init() throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession对象创建dao层的代理对象
userDao = sqlSession.getMapper(UserDao.class);
}
/**
* 释放资源
* @throws IOException
*/
@After
public void destroy() throws IOException {
sqlSession.close();
is.close();
}
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for (User u:users){
System.out.println(u);
}
}
@Test
public void testFindUserByUid(){
User user = userDao.findUserByUid(2);
System.out.println(user);
}
}
d.4多表查询多对多
- 导入依赖
- 创建实体类(所用的表和上一例相同)
package com.wdzl.pojo;
import java.util.List;
public class Role {
private int rid;
private String roleName;
private String roleDesc;
//一个角色可以赋予多个用户
private List<User> users;
public Role() {
}
public Role(int rid, String roleName, String roleDesc) {
this.rid = rid;
this.roleName = roleName;
this.roleDesc = roleDesc;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public int getRid() {
return rid;
}
public void setRid(int rid) {
this.rid = rid;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return "Role{" +
"rid=" + rid +
", roleName='" + roleName + '\'' +
", roleDesc='" + roleDesc + '\'' +
'}';
}
}
package com.wdzl.pojo;
import java.util.List;
/**
* 学生类
* @author lp
* @version 1.0
*/
public class User {
private int uid;
private String username;
private String sex;
private String birthday;
private String address;
//一个用户可以有多个账户
private List<Role> roles;
//一个用户对应多个角色
public User() {
}
public User(int uid, String username, String sex, String birthday, String address, List<Role> roles) {
this.uid = uid;
this.username = username;
this.sex = sex;
this.birthday = birthday;
this.address = address;
this.roles = roles;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", username='" + username + '\'' +
", sex='" + sex + '\'' +
", birthday='" + birthday + '\'' +
", address='" + address + '\'' +
", roles=" + roles +
'}';
}
}
package com.wdzl.pojo;
public class UserRole {
private int uid;
private int rid;
public UserRole() {
}
public UserRole(int uid, int rid) {
this.uid = uid;
this.rid = rid;
}
@Override
public String toString() {
return "UserRole{" +
"uid=" + uid +
", rid=" + rid +
'}';
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public int getRid() {
return rid;
}
public void setRid(int rid) {
this.rid = rid;
}
}
- 建立接口(使用xml方式)
package com.wdzl.dao;
import com.wdzl.pojo.Role;
import java.util.List;
public interface RoleDao {
List<Role> findAll();
}
package com.wdzl.dao;
import com.wdzl.pojo.User;
import java.util.List;
/**
* 操作用户实体类的接口
*/
public interface UserDao {
/**
* 查询用户列表
* @return
*/
List<User> findAll();
}
- 建立接口配置文件
<?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.wdzl.dao.RoleDao"><!--对应dao层接口的全限定类名-->
<resultMap id="roleMap" type="role">
<id property="rid" column="rid"/>
<result property="roleName" column="ROLE_NAME"/>
<result property="roleDesc" column="ROLE_DESC"/>
<collection property="users" ofType="user" column="uid">
<id property="uid" column="uid"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</collection>
</resultMap>
<!--查询用户表-->
<select id="findAll" resultMap="roleMap">
SELECT r.*,u.* FROM role r
LEFT OUTER JOIN user_role ur ON r.rid = ur.rid
LEFT OUTER JOIN USER u ON u.uid = ur.uid
</select>
</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.wdzl.dao.UserDao"><!--对应dao层接口的全限定类名-->
<resultMap id="userMap" type="user">
<id property="uid" column="uid"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<collection property="roles" ofType="role" column="rid">
<id property="rid" column="rid"/>
<result property="roleName" column="ROLE_NAME"/>
<result property="roleDesc" column="ROLE_DESC"/>
</collection>
</resultMap>
<select id="findAll" resultMap="userMap">
-- select * from user u left outer join account a on u.uid = a.uid
SELECT u.*,r.* FROM USER u
LEFT OUTER JOIN user_role ur ON u.uid = ur.uid
LEFT OUTER JOIN role r ON r.rid = ur.rid
</select>
</mapper>
test
package com.wdzl.dao;
import com.wdzl.pojo.Role;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class RoleDaoTest {
InputStream is;
SqlSessionFactory factory;
SqlSession sqlSession;
RoleDao roleDao;
/**
* 初始化
* @throws IOException
*/
@Before
public void init() throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession对象创建dao层的代理对象
roleDao = sqlSession.getMapper(RoleDao.class);
}
/**
* 释放资源
* @throws IOException
*/
@After
public void destroy() throws IOException {
sqlSession.close();
is.close();
}
@Test
public void testFindAll(){
List<Role> roles = roleDao.findAll();
for (Role r: roles){
System.out.println("--------------");
System.out.println(r);
System.out.println(r.getUsers());
}
}
}
package com.wdzl.dao;
import com.wdzl.pojo.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* UserDao测试类
* @author lp
* @version 1.0
* MyBatis入门案例测试实现步骤
* 1. 读取配置文件
* 2.创建SqlSessionFactory工厂
* 3.用工厂生产SqlSession对象
* 4.使用SqlSession对象创建dao层的代理对象
* 5.使用代理对象执行方法
* 6.释放资源
*/
public class UserDaoTest {
InputStream is;
SqlSessionFactory factory;
SqlSession sqlSession;
UserDao userDao;
/**
* 初始化
* @throws IOException
*/
@Before
public void init() throws IOException {
//1.读取配置文件
is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(is);
//3.用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession对象创建dao层的代理对象
userDao = sqlSession.getMapper(UserDao.class);
}
/**
* 释放资源
* @throws IOException
*/
@After
public void destroy() throws IOException {
sqlSession.close();
is.close();
}
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for (User u:users){
System.out.println("----------");
System.out.println(u);
System.out.println(u.getRoles());
}
}
}
e.缓存
概述
存在于内存中的数据叫缓存
应用
减少和数据库的交互,提高执行效率
适用
- 经常查询并且不经常改变的
- 对最终结果影响不大的
不适用
- 经常改变的数据
- 数据的最终结果对结果影响很大的(银行汇率,股票价格)
分类:mybatis中分为一级缓存二级缓存
e.1一级缓存
概述:
它指的是MyBatis中的SqlSession对象的缓存,当我们执行查询后,查询结果会存入到SqlSession为我们提供的一款存储区域中,该区域的存储结构为Map,当我们再次查询同样的数据时,MyBatis首先去一级缓存中查询,如果存在,则直接拿取使用
注意:
当SqlSession对象消失时,MyBatis的一级缓存也会小时
案例
缓存的案例与之前的区别不大,但要在主配置文件开启懒加载
<!--设置懒加载-->
<settings>
<setting name="lazyLoadingEnabled" value="true"/><!--开启懒加载-->
</settings>
**test1.0:**如下userDao获取了两遍id关于对象
@Test
public void testFirstLevelCache(){
//执行查询
User user = userDao.findUserById(1);
System.out.println(user);
User user2 = userDao.findUserById(1);
System.out.println(user2);
System.out.println("-----------");
System.out.println(user==user2);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cbEuo4SS-1616916840115)(C:\Users\dell\Pictures\java截图\懒加载图片1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ZIgE2OL-1616916840115)(C:\Users\dell\Pictures\java截图\懒加载执行图例1.png)]
从以上执行结果来看,获取了两次userDao,执行后的两次结果相同,两相比较也确实时同一个数据,但是我们看第二个图片,当我们第一次执行的结果查询,获取数据后,电脑发现第二个数据与第一个数据相同,这样idea并没有再一次与数据库交互,而是直接将第一个数据再一次返回回来,这样就减少了与数据库交互
test2.0
@Test
public void testFirstLevelCache(){
//执行查询
User user = userDao.findUserById(1);
System.out.println(user);
sqlSession.close();//关闭一级缓存
//重新获取sqlSession
SqlSession sqlSession2 = factory.openSession();
UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
User user2 = userDao2.findUserById(1);
System.out.println(user2);
System.out.println("-----------");
System.out.println(user==user2);
}
而如果我们执行的是以上的代码,可以看到我们将第一次缓存关闭,重新获取SqlSession,这样它又会重新与数据库进行交互
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zy809QjU-1616916840115)(C:\Users\dell\Pictures\java截图\懒加载图片2.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WEiwMdQb-1616916840116)(C:\Users\dell\Pictures\java截图\懒加载执行图例2.0.png)]
e.2二级缓存
概述:
它指的是MyBatis中SqlSessionFactory对象的缓存,在同一个SqlSessionFactory对象创建的SqlSession对象共享二级缓存
开启二级缓存
1.主配置文件中开启二级缓存
<settings>
<setting name="cacheEnabled" value="true"/><!--开启二级缓存-->
</settings>
2.在映射配置文件中开启二级缓存
<!-- 开启二级缓存-->
<cache/>
3.在映射配置文件标签里添加属性useCache=“true”
比如我的
<select id="findUserById" parameterType="int" resultType="user" useCache="true">
select * from user where uid=#{
uid}
</select>
-
一级与二级缓存的区别1
- 一级缓存是SqlSession对象的缓存
- 二级缓存是SqlSessionFactory对象的缓存(SqlSessionFactory可以生产SqlSession对象)
- 我人推测如果有三级缓存,那就是对SqlSessionFactoryBuilder对象的缓存,但是目前MyBatis只有一二级缓存
-
区别2
- 一级缓存只需要在主配置文件中开启
- 二级缓存却更复杂,不仅需要在主配置文件中开启,还要再mapper标签下的namespace对应的区域在做一个标签和属性
个人总结
- MyBatis的实现主要有两个,一个是XML方式的实现,一个是注解方式的实现,二者虽然方法不同,但是殊途同归,而且再使用时也没有太多限制,可以相互使用,这个主要看个人了,如果要了解注释的实现方式可以看d.3多表查询一对多,如果要了解其他方式,我在以上的其他例子都是XML方式实现
ser2);
System.out.println("-----------");
System.out.println(user==user2);
}
[外链图片转存中...(img-cbEuo4SS-1616916840115)]
[外链图片转存中...(img-2ZIgE2OL-1616916840115)]
**<font color='orange'>从以上执行结果来看,获取了两次userDao,执行后的两次结果相同,两相比较也确实时同一个数据,但是我们看第二个图片,当我们第一次执行的结果查询,获取数据后,电脑发现第二个数据与第一个数据相同,这样idea并没有再一次与数据库交互,而是直接将第一个数据再一次返回回来,这样就减少了与数据库交互</font>**
**test2.0**
```java
@Test
public void testFirstLevelCache(){
//执行查询
User user = userDao.findUserById(1);
System.out.println(user);
sqlSession.close();//关闭一级缓存
//重新获取sqlSession
SqlSession sqlSession2 = factory.openSession();
UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
User user2 = userDao2.findUserById(1);
System.out.println(user2);
System.out.println("-----------");
System.out.println(user==user2);
}
而如果我们执行的是以上的代码,可以看到我们将第一次缓存关闭,重新获取SqlSession,这样它又会重新与数据库进行交互
[外链图片转存中…(img-zy809QjU-1616916840115)]
[外链图片转存中…(img-WEiwMdQb-1616916840116)]
e.2二级缓存
概述:
它指的是MyBatis中SqlSessionFactory对象的缓存,在同一个SqlSessionFactory对象创建的SqlSession对象共享二级缓存
开启二级缓存
1.主配置文件中开启二级缓存
<settings>
<setting name="cacheEnabled" value="true"/><!--开启二级缓存-->
</settings>
2.在映射配置文件中开启二级缓存
<!-- 开启二级缓存-->
<cache/>
3.在映射配置文件标签里添加属性useCache=“true”
比如我的
<select id="findUserById" parameterType="int" resultType="user" useCache="true">
select * from user where uid=#{
uid}
</select>
-
一级与二级缓存的区别1
- 一级缓存是SqlSession对象的缓存
- 二级缓存是SqlSessionFactory对象的缓存(SqlSessionFactory可以生产SqlSession对象)
- 我人推测如果有三级缓存,那就是对SqlSessionFactoryBuilder对象的缓存,但是目前MyBatis只有一二级缓存
-
区别2
- 一级缓存只需要在主配置文件中开启
- 二级缓存却更复杂,不仅需要在主配置文件中开启,还要再mapper标签下的namespace对应的区域在做一个标签和属性
个人总结
-
MyBatis的实现主要有两个,一个是XML方式的实现,一个是注解方式的实现,二者虽然方法不同,但是殊途同归,而且再使用时也没有太多限制,可以相互使用,这个主要看个人了,如果要了解注释的实现方式可以看d.3多表查询一对多,如果要了解其他方式,我在以上的其他例子都是XML方式实现
-
MyBatis就是与数据库交互的一项技术,但它更加优于JDBC,也可以说它将JDBC的过程进行了一个封装,省去了这个过程