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.pswp.cn/diannao/41696.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41696.shtml
英文地址,請注明出處:http://en.pswp.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…

面試專區|【54道Spring Cloud高頻題整理(附答案背誦版)】

什么是Spring Cloud&#xff1f; Spring Cloud是一個基于Spring Boot的開源框架&#xff0c;它提供了在分布式系統中集成各種服務治理功能的工具&#xff0c;如配置管理、服務發現、斷路器、智能路由、微代理、控制總線、全局鎖、決策競選、分布式會話和集群狀態等。其主要目…

【推薦圖書】深入淺出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…

c++應用網絡編程之二網絡的IO模型

一、網絡編程的開發平臺 一般來說&#xff0c;目前開發者面對的主流開發平臺就是Windows和類Unix&#xff0c;或者干脆就是Windows和Linux平臺。至于如IBM或其它等公司的相關平臺&#xff0c;可能對絕大多數開發者來說&#xff0c;可能一生都遇不到。至于嵌入式平臺&#xff0…

上位機圖像處理和嵌入式模塊部署(mcu項目1:用戶手冊)

【 聲明&#xff1a;版權所有&#xff0c;歡迎轉載&#xff0c;請勿用于商業用途。 聯系信箱&#xff1a;feixiaoxing 163.com】 一個完整的產品&#xff0c;除了上位機軟件、固件、硬件、包裝之外&#xff0c;一般還需要一個用戶手冊。好的用戶手冊應該能夠兼顧到大多數人的認…

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

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

Python面試題:請解釋 `lambda` 函數是什么,并舉一個例子

lambda函數是Python中用于創建小型匿名函數的一種方式。這些函數通常用于需要一個簡單函數的場景&#xff0c;例如作為參數傳遞給高階函數。lambda函數以lambda關鍵字開始&#xff0c;后跟參數列表和表達式&#xff0c;語法形式如下&#xff1a; lambda arguments: expression…

nginx配置stream代理

項目中遇到某些服務在內網&#xff0c;需要外網訪問的情況&#xff0c;需要配置代理訪問。可用nginx搭建代理服務。 TCP代理 通過nginx的stream模塊可以直接代理TCP服務&#xff0c;步驟如下&#xff1a; 在/etc/nginx/下新建proxy文件夾&#xff0c;用于存放代理配置。此處…

吉洪諾夫正則化隨筆

前言 前幾天在回顧壓縮感知中的特征選擇與LASSO回歸發現了這個Tikhonov regularization&#xff0c;查了一下叫個如題的名字。先來淺說一下正則化這玩意&#xff1a;正則化&#xff08;Regularization&#xff09;是一種用來防止模型過擬合&#xff08;Overfitting&#xff09…

孫溟?篆刻《睡片原諒一切,醒來不問過往》

孫溟?篆刻《睡片原諒一切&#xff0c;醒來不問過往》 佛陀言&#xff1a;睡前原諒一切&#xff0c;醒來不問過往&#xff0c;珍惜所有不期而遇&#xff0c;看淡所有不辭而別甲辰夏溟?于寒舍小窗下刊。