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 configuration
        PUBLIC "-//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 mapper
        PUBLIC "-//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_info
  set 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">
  select
  userName,
  userSex
  from 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  t1
  left 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>

    @Test
    public 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 mapper
        PUBLIC "-//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`   u
        left join `202_userinfo`  ui
        on 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);

测试代码

   @Test
    public 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.找不到配置文件

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PMP–知识卡片--SWOT分析

记忆 SWOT&#xff1a;优劣鸡血&#xff1b; 记忆2&#xff1a; “两条线画成四象限”&#xff0c;即自身优势S/劣势W外部机会O/威胁T&#xff0c;如图&#xff1a; 定义 SWOT分析从优势、劣势、机会、威胁四个角度进行分析&#xff0c;常用于战略管理、项目风险识别。 项…

关于 Mac 系统 .DS_store 文件的起源

原文&#xff1a;Arno - 2006.10.01 &#xff08;前排提醒&#xff1a;可以在 .gitignore 中添加 .DS_Store&#xff0c;否则 git 仓库会存储这个和项目无关的文件。&#xff09; 如果你是 Mac 用户&#xff0c;曾经将文件从 Mac 传输到 Windows&#xff0c;那么可能对 .DS_S…

渲染回调函数将音频传给音频单元

渲染回调函数将音频传给音频单元 渲染回调函数将音频传给音频单元了解音频单元渲染回调函数 渲染回调函数将音频传给音频单元 要将音频从磁盘或内存提供到音频单元输入总线&#xff0c;需使用符合 AURenderCallback 原型的渲染回调函数进行传输。当需要另一片样本帧时&#xf…

实现模型贴图的移动缩放旋转

技术&#xff1a;threejscanvasfabric 效果图&#xff1a; 原理&#xff1a;threejs中没有局部贴图的效果&#xff0c;只能通过map 的方式贴到模型上&#xff0c;所以说换一种方式来实现&#xff0c;通过canvasfabric来实现图片的移动缩放旋转&#xff0c;然后将整个画布以map…

【智能算法应用】麻雀搜索算法SSA优化Kmeans图像分割

目录 1.算法原理2.数学模型3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】麻雀搜索算法&#xff08;SSA&#xff09;原理及实现 2.数学模型 Kmeans是一种无监督的聚类算法,由于参数简洁,时间复杂度低已成功应用于图像分割,取得了良好的分割效果。但传统的 K 均值聚…

Go-知识测试-性能测试

Go-知识测试-性能测试 1. 定义2. 例子3. testing.common 测试基础数据4. testing.TB 接口5. 关键函数5.1 testing.runBenchmarks5.2 testing.B.runN5.3 testing.B.StartTimer5.4 testing.B.StopTimer5.5 testing.B.ResetTimer5.6 testing.B.Run5.7 testing.B.run15.8 testing.B…

无人机便携式侦测干扰设备(定全向)技术详解

无人机便携式侦测干扰设备&#xff08;定全向&#xff09;是一种专门针对无人机进行侦测和干扰的设备。它具备定向和全向两种工作模式&#xff0c;能够覆盖较宽的频率范围&#xff0c;有效侦测并干扰无人机与遥控器之间的通信信号&#xff0c;从而达到控制或驱离无人机的目的。…

1999-2022年企业持续绿色创新水平数据

企业持续绿色创新水平数据为研究者提供了评估企业在绿色技术领域创新持续性和能力的重要视角。以下是对企业持续绿色创新水平数据的介绍&#xff1a; 数据简介 定义&#xff1a;企业持续绿色创新水平反映了企业在一定时期内绿色专利申请的持续性和创新能力。计算方法&#xf…

收银系统源码-营销活动-积分商城

1. 功能描述 营运抽奖&#xff1a;智慧新零售收银系统&#xff0c;线上商城的营销插件&#xff0c;由商户运营&#xff0c;用户通过多种渠道可以获取积分&#xff0c;不仅支持在收银端抵用&#xff0c;还可以在积分商城内兑换优惠券或者真实商品&#xff0c;提升会员活跃度&am…

计算机图形学入门24:材质与外观

1.前言 想要得到一个漂亮准确的场景渲染效果&#xff0c;不只需要物理正确的全局照明算法&#xff0c;也要了解现实中各种物体的表面外观和在图形学中的模拟方式。而物体的外观和材质其实就是同一个意思&#xff0c;不同的材质在光照下就会表现出不同的外观&#xff0c;所以外观…

CH09_JS的循环控制语句

第9章&#xff1a;Javascript循环控制语句 本章目标 掌握break关键字的使用掌握continue关键字的使用 课程回顾 for循环的特点和语法while循环的特点和语法do-while循环的特点和语法三个循环的区别 讲解内容 1. break关键字 为什么要使用break关键字 生活中&#xff0c;描…

MongoDB集群搭建-最简单

目录 前言 一、分片概念 二、搭建集群的步骤 总结 前言 MongoDB分片&#xff08;Sharding&#xff09;是一种水平扩展数据库的方法&#xff0c;它允许将数据分散存储在多个服务器上&#xff0c;从而提高数据库的存储容量和处理能力。分片是MongoDB为了应对大数据量和高吞吐量需…

13 - Python网络编程入门

网络编程入门 计算机网络基础 计算机网络是独立自主的计算机互联而成的系统的总称&#xff0c;组建计算机网络最主要的目的是实现多台计算机之间的通信和资源共享。今天计算机网络中的设备和计算机网络的用户已经多得不可计数&#xff0c;而计算机网络也可以称得上是一个“复…

idea MarketPlace插件找不到

一、背景 好久没用idea了&#xff0c;打开项目后没有lombok&#xff0c;安装lombok插件时发现idea MarketPlace插件市场找不到&#xff0c;需要重新配置代理源&#xff0c;在外网访问时通过代理服务进行连接 二、操作 ### File-->setting 快捷键 Ctrl Alt S 远端源地…

uni-app 使用Pinia进行全局状态管理并持久化数据

1.引言 最近在学习移动端的开发&#xff0c;使用uni-app前端应用框架&#xff0c;通过学习B站的视频以及找了一个开发模板&#xff0c;终于是有了一些心得体会。 B站视频1&#xff1a;Day1-01-uni-app小兔鲜儿导学视频_哔哩哔哩_bilibili B站视频2&#xff1a;01-课程和uni的…

hdu物联网硬件实验1 小灯闪烁

物联网硬件基础实验报告 学院 班级 学号 姓名 日期 成绩 实验题目 配置环境小灯 实验目的 配置环境以及小灯闪烁 硬件原理 无 关键代码及注释 /* Blink The basic Energia example. Turns on an LED on for one second, then off for one sec…

01 Web基础与HTTP协议

1.1 Web 基础 本章将介绍 Web 基础知识&#xff0c;包括域名的概念、DNS 原理、静态网页和动态网页的相关知识。 1.1.1.域名概述 1.域名的概念 ip地址不易记忆 2.早期使用host文件解析域名 主机名重复主机维护困难 3.DNS 分布式层次式 4.域名空间结构 根域顶级域 组…

在原有的iconfont.css文件中加入新的字体图标

前言&#xff1a;在阿里图标库中&#xff0c;如果你没有这个字体图标的线上项目&#xff0c;那么你怎么在本地项目中的原始图标文件中添加新的图标呢&#xff1f; 背景&#xff1a;现有一个vue项目&#xff0c;下面是这个前端项目的字体图标文件。现在需要新开发功能页&#x…

使用POI实现Excel文件的读取(超详细)

目录 一 导入poi相关的maven坐标 二 实现创建并且写入文件 2.1实现步骤 2.2实现代码 2.3效果展示 ​编辑 2.4注意 三 实现从Excel文件中读取数据 3.1实现步骤 3.2实现代码 3.3结果展示 一 导入poi相关的maven坐标 <!-- Apache poi --><dependency><gro…