Mybatis原生使用

一、MyBatis初次使用

2.1 环境搭建步骤

MyBatis 的 API : https://mybatis.org/mybatis-3/zh/getting-started.html

1.引入依赖包

2.准备核心配置件

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://123.57.206.19:3306/demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username=root
password=123456

mybatis.xml

在resources下定义MyBatis的配置文件,无固定名,但大部分人使用 resources/mybatis.xml.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="db.properties"></properties>
<!--    <settings>-->
<!--        <setting name="logImpl" value="LOG4J"/>-->
<!--    </settings>--><typeAliases><!--给单个类起别名。 type:类型 alias:别名--><typeAlias type="com.test.pojo.Student" alias="student"></typeAlias><!--给指定包下所有类起别名。 别名=类名(不区分大小写)--><package name="com.test.pojo"/></typeAliases><!--    配置mybaits中数据库连接环境--><environments default="mysql"><environment id="mysql"><!--配置myabtis中事务 和 JDBC 保持一致--><transactionManager type="JDBC"></transactionManager><!-- 配置连接数据库的4个元素, 底层采用的是数据库连接池的方式--><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--扫描mapper文件--><mappers><mapper resource="mapper/student.xml"></mapper></mappers>
</configuration>

3.书写mapper文件

resources/**.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace: 代表xml的名称,类似java包名-->
<mapper namespace="com.beiyou.dao.StudentDao"><!-- 查询所有学生 List<Student> selectAll()--><!--select: 代表进行查询操作。id: 之前的方法名称,具有唯一性。resultType: 返回值类型。如果返回的是对象,直接书写对象类型的的完整名。如果是集合,书写的是集合的泛型parameterType: 参数类型,可以省略。--><select id="selectAll" resultType="com.beiyou.entity.Student"  >select * from student</select></mapper>

非必需

<build><resources><resource><directory>src/main/java</directory><!--所在的目录--><includes><!--.xml 文件都会扫描到,包括子目录--><include>**/*.xml</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources>
</build>

4.构建SqlSessionFactory。

从xml中创建SqlSessionFactory.

// 1. 解析扫码 mybatis.xml 文件
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
// 2. 获取sqlsession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3. 获得 sqlsession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4. 执行sql语句
List<Student> students = sqlSession.selectList("com.beiyou.dao.StudentDao.selectAll");
// 打印结果
System.out.println(students);

是否弥补了JDBC的不足?

二、MyBatis 配置细节

2.1 log4j的使用

  1. 加入依赖

<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>

  1. 配置文件 log4j.properties

#定义全局日志级别调试阶段推荐debug
log4j.rootLogger = error,stdout
#包级别日志
log4j.logger.test.a = debug### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.SimpleLayout### 输出日志到文件=/logs/log.log ###
log4j.appender.logfile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.File = /logs/log.log
log4j.appender.logfile.layout = org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

2.2 事务配置

transactionManager.type

JDBC : 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。

MANAGED : 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。

2.3 连接池配置

dataSource.type

UNPOOLED : 这个数据源的实现会每次请求时打开和关闭连接.

POOLED : 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。

​ JNDI : 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。

2.4 映射文件的加载方式

1.resource: 使用相对于类路径的资源引用。

 <mapper resource="AuthorMapper.xml"/>

2.url: 使用完全限定资源定位符(URL)

 <mapper url="file:///D:/207/mybatis/src/main/resources/mapper/BlogMapper.xml"/>

3.class : 使用映射器接口实现类的完全限定类名

 <mapper class="org.mybatis.builder.BlogMapper"/>

4.name : 将包内的映射器接口实现全部注册为映射器

<mappers><package name="com.beuyou.dao"/>
</mappers>

2.5 实体类别名处理

<typeAliases><!--给单个类起别名。 type:类型 alias:别名--><typeAlias type="com.beiyou.entity.Student" alias="student"></typeAlias><!--给指定包下所有类起别名。 别名=类名(不区分大小写)--><package name="com.beuyou.entity"/>
</typeAliases>

常见的 Java 类型内建的类型别名。它们都是不区分大小写的

别名

映射的类型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

object

Object

map

Map

hashmap

HashMap

list

List

arraylist

ArrayList

collection

Collection

iterator

Iterator

2.6 外部属性配置文件存储数据库信息

  1. 配置db.properties数据库信息

driver=com.mysql.cj.jdbc.Driver
url=mysql://rm-bp169j3q9n43kxauzco.mysql.rds.aliyuncs.com:3306?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username=root123
password=Root_123

<properties resource="db.properties"></properties><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource>

三、Mapper文件配置

3.1 常用属性

3.2 SQL 定义标签

1. select

用于数据查询操作,例:

<select id="selectUserInfo" parameterType="int" resultType="map">select * from user_info where id=#{keyId}
</select>

2. insert

用于数据保存操作,例:

<insert id="insertUserInfo" parameterType="map" useGeneratedKeys="true" keyProperty="keyId">insert into user_info (userName,userSex)values(#{userName},#{userSex})
</insert>

PS:keyProperty属性可返回此条插入数据的主键值

3. update

用于数据更新操作,例:

<update id="updateUserInfo" parameterType="map">update  user_infoset userName=#{userName}where id=#{keyId}
</update>

4. delete

用于数据删除操作,例:

<delete id="selectUserInfo" parameterType="int">delete  from user_info where id=#{keyId}
</delete>

5. resultMap

SQL返回与实体类映射关系信息,例

<resultMap id="userInfoMap" type="User"><result property="user_name" column="userName"/><result property="user_sex" column="userSex"/>
</resultMap>

<select id="selectUserInfo" parameterType="int" resultType="userInfoMap">selectuserName,userSexfrom user_info where id=#{keyId}
</select>

将数据表字段userName、userSex映射到实体类User的user_name、user_sex

6. sql

用于定义可重用的 SQL 代码片段,以便在多个SQL语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。例:

<!-- 定义 -->
<sql id="userColumns"> ${alias}.userName,${alias}.userSex</sql>

<!-- 运用 -->
<select id="selectUserInfo" resultType="map">select<include refid="userColumns"><property name="alias" value="t1"/></include>,<include refid="userColumns"><property name="alias" value="t2"/></include>from user_info  t1left join user_info_copy t2
</select>

3.3、SQL动态标签

1. if

单个条件判断,用以实现条件筛选,例:

<select id="selectUserInfo" parameterType="map" resultType="map">select * from user_info where 1=1<if test="userSex !=null and userSex !='' ">and userSex=#{userSex}</if><if test="userName !=null and userName !='' ">and userName like CONCAT('%',#{userName},'%')</if>
</select>

2. foreach

用于更新或保存数据时的批量操作,例:

<!-- userList为List<HashMap<String,Object>>类型数据 -->
insert into user_info(
userName,
userSex
)values
<foreach item="item" index="index" collection="userList" separator="," >
(
#{item.userName},
#{item.userSex}
)
</foreach>

<!-- userList为List<String>类型数据 -->
insert into user_info(
userName
)values
<foreach item="item" index="index" collection="userList" separator="," >
(
#{userName}
)
</foreach>

update user_info
set userAge=#{userAge}
where id in
<foreach collection="keyIds" index="index" item="item" separator="," open="(" close=")">
#{item}
</foreach>

3. choose/when/otherwise

用以实现条件的多种判断,类似与if else,例:

<select id="selectUserInfo" parameterType="map" resultType="map">select * from user_info where 1=1<choose><when test="userFlag!=null and userFlag!='' and userFlag=='Y'">and id<=100</when><when test="userFlag!=null and userFlag!='' and userFlag=='N'">and id <=200</when><otherwise>and id<=300</otherwise></choose>
</select>

4. where

只会在子元素返回任何内容的情况下才插入 “WHERE” 子句,并且可以自动处理判断条件语句返回的第一个and或or,例:

不使用where标签时,若userSex为空,语法错误会报错:

<select id="selectUserInfo" parameterType="map" resultType="map">select * from user_info where<if test="userSex !=null and userSex !='' ">userSex=#{userSex}</if><if test="userName !=null and userName !='' ">and userName like CONCAT('%',#{userName},'%')</if>
</select>

修改为:

<select id="selectUserInfo" parameterType="map" resultType="map">select * from user_info<where><if test="userSex !=null and userSex !='' ">userSex=#{userSex}</if><if test="userName !=null and userName !='' ">and userName like CONCAT('%',#{userName},'%')</if></where>
</select>
自动转换为:select * from user_info where userName like ……

5. set

可以动态更新需要更新的列,忽略其它不更新的列,例:

<update id="updateUserInfo" parameterType="map">update  user_info<set><if test="userName!= null and userName!=''">userName=#{userName},</if>userSex=#{userSex}</set>where id=#{keyId}
</update>

四、基于MyBatis的CURD操作

使用单元测试验证

  <dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.6.0</version><scope>test</scope></dependency>

4.1 MyBatis查询的三种方式

  1. 返回单个对象 selectOne

  2. 返回对象List集合 selectList

  3. 返回对象Map集合 selectMap

<select id="selectOne" resultType="student">select *  from student where id=1
</select>
<select id="selectAll" resultType="student"  >select * from student
</select>
<select id="selectMap" resultType="map">select *  from student
</select>

4.2 MyBatis参数传递的三种方式

4.2.1 三种传参

  1. 传递的是基本类型+String ,使用 param1

  2. 传递类型是对象,接受使用对象的 属性名

  3. 传递的是map集合,接受时候使用map中的 key

<!-- 方法 Student selectOne(int id)-->
<!--param1:-->
<select id="selectOne" resultType="student" parameterType="int">select *  from student where id = #{id}
</select>
<!-- 方法 Student selectOne(StudentQuery query)-->
<!--#{} 里面放的是对象属性-->
<select id="selectOne2" resultType="student">select *  from student where id = #{id} and name = #{name}
</select>
<!-- 方法 Student selectOne(Map map)-->
<!--#{} 里面放的是map的key-->
<select id="selectOne3" resultType="student">select *  from student where id = #{a} and name = #{b}
</select>

// 【A】. 传递基本类型Student student = sqlSession.selectOne("test.c.selectOne", 2);// 打印System.out.println(student);// 【B】. 传递对象StudentQuery query = new StudentQuery();query.setId(2);query.setName("周星星");Student student = sqlSession.selectOne("test.c.selectOne2", query);//打印System.out.println(student);//【C】. 传递Map集合//id,name 一块封装到map集合Map<String,Object> map = new HashMap<>();map.put("a",2);map.put("b","周星星");Student student = sqlSession.selectOne("test.c.selectOne3", map);//打印System.out.println(student);

4.2.2 #和$区别:面试题

#:底层相当于占位符?

$:底层相当于字符串拼接

  1. 两者相比,占位符的方式更加方便,可以有效的防止SQL注入。

  2. 预编译

4.2.3 模糊查询

<!-- 模糊查询 -->
<select id="selectOne4" resultType="student">Student student = sqlSession.selectOne("test.c.selectOne4", "%敏%");select *  from student where  name like #{param1}Student student = sqlSession.selectOne("test.c.selectOne4", "敏");select *  from student where name like concat('%',#{param1},'%')
</select>

4.2.4 Model对象字段名称与数据库不一致,使用resultMap指定

 <select id="selectlike2" resultMap="usermap" >select *  from user where email like concat('%',#{param1},'%')</select><resultMap id="usermap" type="User"><!--主键映射  使用id标签propetry java中的类型名称column  数据库中的字段名--><id property="pwd" column="password"/></resultMap>

XML

4.2.5 include标签

1、首先定义一个sql标签,一定要定义唯一id。    <sql id="columns">id, title ,brief</sql>
2、然后通过id引用 <select id="selectOne"  resultMap="productResultMap1" >select<include refid="columns"/>from product where id = 8</select>

XML

4.3 MyBatis完整DML全部操作

DML与DDL的含义:

1、DML(Data Manipulation Language)数据操作语言-数据库的基本操作,SQL中处理数据等操作统称为数据操纵语言,简而言之就是实现了基本的“增删改查”操作。包括的关键字有:select、update、delete、insert、merge

2、DDL(Data Definition Language)数据定义语言-用于定义和管理 SQL 数据库中的所有对象的语言,对数据库中的某些对象(例如,database,table)进行管理。包括的关键字有:

create、alter、drop、truncate、comment、grant、revoke

4.3.1 CUD

【1】新增

<!-- 方法 int insert(Student student)-->
<insert id="insert">insert into student (name,age) values (#{name},#{age})
</insert>

Student student = new Student();
student.setName("邓超");
student.setAge(38);
int rowNum  = sqlSession.insert("com.beiyou.dao.StudentMapper.insert", student);
//MyBatis 默认不自动提交事务,所以 增删改功能 需要我们手动提交事务
sqlSession.commit();

【2】修改

<!-- 传统方法 int update(Student student)-->
<update id="update">update student set name = #{name},age = #{age} where id = #{id}
</update>

Student student = new Student();
student.setName("邓超111");
student.setAge(380);
student.setId(6);
int rowNum  = sqlSession.update("com.beiyou.dao.StudentMapper.update", student);
//MyBatis 默认不自动提交事务,所以 增删改功能 需要我们手动提交事务
sqlSession.commit();

【3】删除

<!-- 传统方法 int delete(int id)-->
<delete id="delete">delete from student  where id = #{param1}
</delete>

int rowNum  = sqlSession.delete("test.d.delete", 6);
//MyBatis 默认不自动提交事务,所以 增删改功能 需要我们手动提交事务
sqlSession.commit();

4.3.2 设置SqlSession提交

MyBatis 默认不自动提交事务,所以 增删改功能 需要我们手动提交事

【1】SqlSession sqlSession = factory.openSession(true);

【2】sqlSession.commit();

4.4 扩展

4.4.1 接口编程

package com.beiyou.dao;public interface UserDao {List<User> selectAll();
}

<mapper namespace="com.beiyou.dao.UserDao"><select id="selectAll" resultType="user" >select  *  from 202_user</select></mapper>

  UserDao mapper = sqlSession.getMapper(UserDao.class);mapper.selectAll();

4.4.2通过表达式,实现多场景多条件组合查询

<select id="select" resultMap="productResultMap1">select id, categoryId,title ,brief from 202_product<where><if test="id != null">and  id = #{id}</if><if test="ids != null">and id in<foreach collection="ids" item="item"  open="(" close=")" separator=",">#{item}</foreach></if><if test="categoryId != null">and  categoryId= #{categoryId}</if><if test="categoryIds != null">and categoryId in<foreach collection="categoryIds" item="item" open="(" close=")" separator=",">#{item}</foreach></if><if test="name != null">and title like concat('%',#{name},'%')</if></where></select>

    @Testpublic void selectQuery() throws IOException {ProductDao productDao = sqlSession.getMapper(ProductDao.class);ProductQuery query = new ProductQuery();//query.setId(40);//query.setCategoryId(1);//query.setName("梨38");//query.setIds(new Integer[]{38,42,50,51,52});query.setCategoryIds(new Integer[]{3});List<Product> products = productDao.select(query);System.out.println(products);}

4.4.3 注解

 <mapper class="com.beiyou.dao.UserDao"/>

public interface UserDao {@Select("select *  from  202_user limit 1")User select();  //insert into order_item (productId,productName,productImg,price,qty,orderId)  values (1,2,3),(2,3,4).....@Insert("<script> " +"insert into "  +" order_item (productId,productName,productImg,price,qty,orderId) " +"values " +"<foreach collection='items'  item='item' separator=','> "+"(#{item.productId},#{item.productName},#{item.productImg},#{item.price},#{item.qty},#{item.orderId})"+"</foreach> </script>" )int insertAll(List<OrderItemEntity> items);@Select("<script> " +"select *  from  order_item where 1 = 1 "  +"<if test='id != null'>" +" and id = #{id} "+"</if> "+"<if test='orderId != null'>" +" and orderId = #{orderId} "+"</if> "+"<if test='orderIds != null'>" +" and orderId in  "+"<foreach collection='orderIds' open='(' close=')'  item='item' separator=','> "+"#{item}"+"</foreach> "+"</if> "+"</script>" )@Results(id="studentMap",value={    @Result(column=“id”, property=“id”, jdbcType=JdbcType.INTEGER, id=true),    @Result(column=“name”, property=“name”, jdbcType=JdbcType.VARCHAR),    @Result(column=“class_id”, property=“classId”, jdbcType=JdbcType.INTEGER)})List<OrderItemEntity> select(OrderItemQueryDto queryDto);}

4.4.4 SelecKey标签使用

Mybatis之useGeneratedKeys和selectKey的基本用法与区别_mybatis selectkey usegeneratedkeys_poppyCL的博客-CSDN博客

一、useGeneratedKeys数据库本身具备主键自动增长的功能,才能使用useGeneratedKeysoracle不支持true<insert id="insert" useGeneratedKeys="true" keyProperty="idColName"> insert into tableName (colName) values (#{colVal,jdbc..._mybatis selectkey usegeneratedkeys

https://blog.csdn.net/poppyCL/article/details/103347385

   <insert id="insert"  parameterType="UserEntity">insert user (email,password) values (#{email},#{pwd})<selectKey keyProperty="id" resultType="integer" keyColumn="newId" order="AFTER">SELECT LAST_INSERT_ID() as newId</selectKey></insert><selectKey resultType="integer" keyColumn="newId" keyProperty="id" order="BEFORE">SELECT (max(id)+1) as newId from  205_category
</selectKey>

注解版

@SelectKey(statement="SELECT last_insert_id", keyProperty="id", before=false, resultType=Long.class)

五 MyBatis 高级关系查询

  • 一个会员只属于一个详情 ==> 会员对详情表是一对一关系

  • 不管是一对一还是多对多,都要使用<resultMap> ,属性有id 和type

  • 一对一中,<resultMap>内要用<association>来映射复杂对象,属性有 :

  •   (property和javaType) ==> 嵌套结果

  •   (property, column, select) ==> 嵌套查询

  • 一对多中,<resultMap>内要用<collection>来映射复杂对象,属性有property和ofType

  • 注意防范<resultMap>和<association>或<collection>中字段名冲突的问题!

5.1 一对一

<resultMap> <association>

<association> 元素,通常可以配置一下属性

- propery:指定映射到实体类对象属性,与表字段一一对应

- column:指定表中对应的字段

- javaType:指定映射到实体对象属性的类型

- select:指定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询

- fetchType:指定在关联查询时是否启用延迟加载。FetchType属性有lazy和eager(实时)两个属性值,默认值为lazy

默认为lazy(默认关联映射延迟加载)

create table 202_user(    id int unsigned auto_increment,    tel varchar(50) not null,    password varchar(32) not null,    primary key(id));
CREATE TABLE `202_userinfo` (`id` int NOT NULL AUTO_INCREMENT COMMENT '唯一标识',`name` varchar(100) NOT NULL COMMENT '姓名',`sex` varchar(100) DEFAULT NULL COMMENT '性别',PRIMARY KEY (`id`)
)

实体对象

@Data public class User {    private Integer id;    private String tel;    private String password;    private UserInfo userinfo;}public class UserInfo {    private Integer id;    private String name;    private String sex;   private Integer age;
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.beiyou.dao.UserDao2"><resultMap id="usermap" type="com.beiyou.model.User"><id property="id" column="id"/><result property="tel" column="tel"/><result column="password" property="password"/><association property="userInfo" javaType="com.beiyou.model.UserInfo"><id property="id" column="id"/><result property="name" column="name"/><result property="sex" column="sex"/></association></resultMap><select id="one2one" resultMap="usermap" >select *from `202_user`   uleft join `202_userinfo`  uion u.id = ui.userId</select><resultMap id="userMap" type="com.beiyou.model.User"><id column="id" property="id"/><result column="tel" property="tel"/><result column="password" property="password"/><association property="userInfo" column="Id"  fetchType="lazy" javaType="com.beiyou.model.UserInfo"select="selectUserinfo"><id property="id" column="id"/>   bug 必须书写<result property="name" column="name"/><result property="sex" column="sex"/></association></resultMap><select id="lazyone2one" resultMap="usermap2">select  *  from  202_user</select><select id="selectName" resultType="com.beiyou.model.UserInfo">select * from 202_userinfo where userId = #{id}</select>
</mapper>

UserDao.java

public interface UserDao {User one2one(String name);User lazyone2one(String name);
}

5.2 一对多

<resultMap> <collection>

CREATE TABLE `202_address` (`id` int NOT NULL AUTO_INCREMENT COMMENT '唯一id',`userId` int NOT NULL COMMENT '用户编号',`province` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '省',`city` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '市',`address` varchar(100) DEFAULT NULL COMMENT '详细地址',PRIMARY KEY (`id`)
)

<resultMap id="userMap" type="com.beiyou.model.User"><id column="id" property="id"/><result column="tel" property="tel"/><result column="password" property="password"/><association property="userInfo" column="Id"  fetchType="lazy" javaType="com.beiyou.model.UserInfo"select="selectUserinfo"><id property="id" column="id"/><result property="name" column="name"/><result property="sex" column="sex"/></association><collection property="addresses" column="id" fetchType="lazy" javaType="java.util.ArrayList"ofType="com.beiyou.model.Address"  select="selectAddress" ><id property="id" column="id"/><result property="province" column="province"/><result property="city" column="city"/><result property="county" column="county"/><result property="address" column="address"/></collection>
</resultMap><select id="selectAddr" resultType="com.beiyou.model.Address">select * from 202_address where userId = #{userId}</select>

使用Mapper注解,实现一对一和一对多关系查询

@Results(id="userMap", value = {@Result(column = "id", property = "id", id = true),@Result(column = "tel", property = "tel"),@Result(column = "password", property = "password"),@Result(property = "userInfo", column = "id",one = @One(select = "selectUserinfo",fetchType = FetchType.LAZY)), 可以不用写具体映射,但是用xml的时候,必须写@Result(column = "id",  property = "addresses" ,many = @Many(select = "selectAddress",fetchType = FetchType.LAZY))})}@Select("select  *  from 202_user  u   where u.id = #{id}")List<User> layeOne2One(int id);@Select("select  *  from 202_address where userId = #{id}")List<Address> selectAddress(Integer id);

测试代码

   @Testpublic void test(){UserMapper2 dao = sqlSession.getMapper(UserMapper2.class);List<User> users = dao.queryUserAll();}

Java

六 MyBatis缓存机制

mybatis.xml

   <settings><setting name="cacheEnabled" value="true"/> //开启全局的二级缓存</settings>

//清空缓存数据@Options(flushCache = Options.FlushCachePolicy.TRUE)@Select(" select *  from  202_user where id= 46")User  one();

6.1 一级缓存

一级缓存作用域是sqlsession级别的,同一个sqlsession中执行相同的sql查询(相同的sql和参数),第一次会去查询数据库并写到缓存中,第二次从一级缓存中取。

一级缓存是基于 PerpetualCache 的 HashMap 本地缓存,默认打开一级缓存。

6.1.1何时清空一级缓存

如果中间sqlSession去执行commit操作(执行插入、更新、删除),则会清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

一级缓存时执行commit,close,增删改等操作,就会清空当前的一级缓存;当对SqlSession执行更新操作(update、delete、insert)后并执行commit时,不仅清空其自身的一级缓存(执行更新操作的效果),也清空二级缓存(执行commit()的效果)。

6.1.2一级缓存无过期时间,只有生命周期

MyBatis在开启一个数据库会话时,会创建一个新的SqlSession对象,SqlSession对象中会有一个Executor对象,Executor对象中持有一个PerpetualCache对象。当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。

6.2 二级缓存

它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。

同一个工厂生产的sqlsession,批次号相同.

二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

6.2.1 二级缓存何时存入

在关闭sqlsession后(close或commit),才会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。

开启了二级缓存后,还需要将要缓存的pojo实现Serializable接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中

6.2.2二级缓存有过期时间

每当存取数据的时候,都有检测一下cache的生命时间,默认是1小时,如果这个cache存活了一个小时,那么将整个清空一下.

6.2.3 执行流程

当 Mybatis 调用 Dao 层查询数据库时,先查询二级缓存,二级缓存中无对应数据,再去查询一级缓存,一级缓存中也没有,最后去数据库查找。

SqlSessionFactory级别缓存,会话工厂级别SqlSession s1 = sf.openSession();SqlSession s2 = sf.openSession();SqlSession s3 = sf.openSession();System.out.println(s1);System.out.println(s2);System.out.println(s3);开发者必须自己配置二级缓存二级缓存是人工开启的,需要在XxxxMapper.xml 文件中加入如下开启方法一<cache eviction="FIFO" flushInterval="60000" size="5120" readOnly="true" /><select id="queryAll" resultType="book" useCache="false">  默认使用缓存,填写false此操作不让缓存select * from book</select>方法二@CacheNamespace(eviction = FifoCache.class, flushInterval = 60000, size = 1024, readWrite = true)public interface BookMapper {@Select("select * from book") @Options(useCache = true)public List<Book> queryAll();@Select("select * from book where id = #{id}")public Book queryById(int id);}           注意:使用缓存时,最好给实体类序列化。

Java

Student.java

@Data
public class Student implements Serializable {private int id;private String name;private int age;private double money;private String info;
}

Plain Text

StudentMapper.java

@CacheNamespace 
public interface StudentMapper {@Select("select * from t_student")@Options(useCache = true) //开启或关闭二级缓存public List<Student> page();@Select("select * from t_student where id = #{id}")@Options(useCache = true)public Student queryById(int id);
}

Java

@Test
public void t5() {var session = sf.openSession();var sm = session.getMapper(StudentMapper.class);System.out.println(sm.page());System.out.println(sm.page());System.out.println(sm.page());System.out.println(sm.page());System.out.println("---------------------------");System.out.println(sm.queryById(5));session.commit();//将当前会话的查询,保存到二级缓存中,System.out.println(sm.queryById(5));System.out.println(sm.queryById(5));System.out.println(sm.queryById(5));System.out.println("----------------------");var s2 = sf.openSession();var sm2 = s2.getMapper(StudentMapper.class);System.out.println(sm2.queryById(5));
}

Plain Text

六 常见问题

1.MySQL连接数据库时,添加语句:“allowMultiQueries=true”的作用:

  1. 可以在sql语句后携带分号,实现多语句执行。

  2. 可以执行批处理,同时发出多个SQL语句。

2.找不到配置文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/41696.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何选择最佳的照片和视频恢复软件

您是否意外从硬盘或 USB 卡中删除了照片或视频&#xff1f;最好的视频和照片恢复软件可以帮到您&#xff01;如果您一直在寻找最好的照片恢复软件&#xff0c;那么您来对地方了。本文将分享一些帮助您找到最佳视频恢复软件的提示。 重要提示&#xff1a;事实&#xff1a;媒体文…

【LabVIEW学习篇 - 3】:程序结构——顺序结构、for循环、while循环

文章目录 顺序结构案例一案例二 for循环while循环 顺序结构 LabVIEW中的顺序结构是一种常用的控制结构&#xff0c;用于按顺序执行程序的不同部分。顺序结构在程序中按照从左到右的顺序依次执行各个子结构&#xff0c;类似于传统的文本编程语言中的顺序执行。 案例一 案例一…

JAVA的线性表数据结构的超详解

目录 顺序表的顺序存储结构 1.数组 2.顺序表 顺序表的声明&#xff0c;存储操作以及效率分析 1.泛型类 2.顺序表的插入操作 3. 顺序表的删除操作 4.顺序表查询操作 5.顺序表的应用 线性表的链式存储结构 单链表的基本操作 顺序表的顺序存储结构 数组是实现顺序存储…

随手记录: Ubuntu NVIDIA显卡驱动安装后 屏幕亮度无法调节 无法连接外显示器等问题

背景 一句话&#xff1a;简单记录帮身边人装系统发现 GPU和外接显示器的无法连接&#xff0c;同时亮度无法调节等新问题 设备型号&#xff1a; 联想笔记本&#xff1a;ThinkBook 16p Gen2CPU&#xff1a;AMD Ryzen 7 5800HGPU&#xff1a;RTX 3060 问题描述及流程&#xff…

类继承-多继承虚继承

#include<iostream> using namespace std; class A1 { public:int a 10;}; class A2 { public:int b 20; }; class B :public A1, public A2 { public:int c 30; }; int main(){B b;cout << b.a << b.b << b.c << endl;return 0; } 如果基类…

STM32-HAL-SDIO-(sd卡的识别,整理后的版本)

1STM32Cube操作 1-1配置时钟 1-2配置调试端口 1-3配置uart 1-4配置SDIO 选择数据传输引脚个数 需改配置&#xff08;图中改了两处&#xff0c;选中的和最后一个&#xff09; 1-5打开DMA 传输方向改为图中的&#xff08;由内转向外设&#xff09;在改图中的一次读写的大小 1-…

图像处理调试软件推荐

对于图像处理的调试&#xff0c;使用具有图形用户界面&#xff08;GUI&#xff09;且支持实时调整和预览的图像处理软件&#xff0c;可以大大提高工作效率。以下是几款常用且功能强大的图像处理调试软件推荐&#xff1a; ImageJ/FijiMATLABOpenCV with GUI LibrariesNI Vision …

Java中关于构造代码块和静态代码块的解析

构造代码块 特点&#xff1a;优先于构造方法执行,每new一次,就会执行一次 public class Person {public Person(){System.out.println("我是无参构造方法");}{System.out.println("我是构造代码块"); //构造代码块} }public class Test {public stati…

【推荐图书】深入浅出Spring Boot 3.x

推荐原因 这部SpringBoot3.x经典之作&#xff0c;时隔六年迎来重磅升级&#xff01; 适合java开发相关读者 购买链接 商品链接&#xff1a;https://item.jd.com/14600442.html 介绍 书名&#xff1a;深入浅出Spring Boot 3.x ISBN&#xff1a;978-7-115-63282-1/ 作者&…

「ETL趋势」分区支持PostgreSQL、Greenplum、Gauss200, 定时任务支持Kettle

FineDataLink作为一款市场上的顶尖ETL工具&#xff0c;集实时数据同步、ELT/ETL数据处理、数据服务和系统管理于一体的数据集成工具&#xff0c;进行了新的维护迭代。本文把FDL4.1.9最新功能作了介绍&#xff0c;方便大家对比&#xff1a;&#xff08;产品更新详情&#xff1a;…

【国产开源可视化引擎Meta2d.js】钢笔

钢笔 钢笔是和其他众多绘图工具&#xff08;Photoshop、Sketch、Illustrator&#xff09;中一致的钢笔工具&#xff0c;能够很方便的在线绘制各种小图标 在线体验&#xff1a; 乐吾乐2D可视化 示例&#xff1a; // 开始绘画&#xff1a;curve。除了curve&#xff0c;还有poly…

上位机图像处理和嵌入式模块部署(mcu项目1:用户手册)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 一个完整的产品&#xff0c;除了上位机软件、固件、硬件、包装之外&#xff0c;一般还需要一个用户手册。好的用户手册应该能够兼顾到大多数人的认…

力扣(3200)- 三角形的最大高度

好方法&#xff1a; 垃圾方法&#xff1a;

吉洪诺夫正则化随笔

前言 前几天在回顾压缩感知中的特征选择与LASSO回归发现了这个Tikhonov regularization&#xff0c;查了一下叫个如题的名字。先来浅说一下正则化这玩意&#xff1a;正则化&#xff08;Regularization&#xff09;是一种用来防止模型过拟合&#xff08;Overfitting&#xff09…

孙溟㠭篆刻《睡片原谅一切,醒来不问过往》

孙溟㠭篆刻《睡片原谅一切&#xff0c;醒来不问过往》 佛陀言&#xff1a;睡前原谅一切&#xff0c;醒来不问过往&#xff0c;珍惜所有不期而遇&#xff0c;看淡所有不辞而别甲辰夏溟㠭于寒舍小窗下刊。

相关向量机RVM算法介绍继承sklearn-SVM-API实现回归预测算例

一、相关向量机RVM与支持向量机SVM对比 1、相关向量机&#xff08;RVM&#xff09; ①定义与原理 相关向量机&#xff08;Relevance Vector Machine, RVM&#xff09;是一种基于概率模型的机器学习算法&#xff0c;主要用于分类和回归分析。基于稀疏贝叶斯学习框架&#xff…

Springboot助农农产品销售系统-计算机毕业设计源码16718

摘要 SpringBoot助农农产品销售系统旨在通过利用SpringBoot框架开发一个便捷高效的农产品销售平台。该系统包括用户注册登录、商品浏览、购物车管理、订单生成、支付功能等模块。通过整合支付接口、地图定位、推荐系统等技术&#xff0c;提供给用户更好的购物体验。本文介绍了…

Docker安装遇到问题:curl: (7) Failed to connect to download.docker.com port 443: 拒绝连接

问题描述 首先&#xff0c;完全按照Docker官方文档进行安装&#xff1a; Install Docker Engine on Ubuntu | Docker Docs 在第1步&#xff1a;Set up Dockers apt repository&#xff0c;执行如下指令&#xff1a; sudo curl -fsSL https://download.docker.com/linux/ubu…

人工智能开发中的数据隐私

人工智能开发中的数据隐私对于建立用户信任和遵守严格法规至关重要。保护敏感信息可确保合乎道德的人工智能使用并防止有害的数据泄露。 为什么在人工智能开发中优先考虑数据隐私至关重要 人工智能的迅猛发展开启了一个前所未有的技术进步时代&#xff0c;彻底改变了各行各业&…

使用Python绘制双向条形图

使用Python绘制双向条形图 双向条形图效果代码 双向条形图 双向条形图用于比较两个类别的数值分布&#xff0c;条形在中轴线两侧对称排列。这种图表常用于显示两个变量的对比情况&#xff0c;例如男女不同年龄段人口数量对比。 效果 代码 import matplotlib.pyplot as plt i…