Mybatis原生使用

news2024/11/20 2:31:00

一、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.找不到配置文件

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

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

相关文章

步进电机改伺服电机

步进电机&#xff1a; 42&#xff1a;轴径5mm 57&#xff1a;轴径8mm 86&#xff1a;轴径14mm 【86CME120闭环】// 12牛米 伺服电机&#xff1a; 40&#xff1a; 60&#xff1a; 80&#xff1a; 86&#xff1a; ECMA——C 1 0910 R S 4.25A 轴径…

26.5 Django模板层

1. 模版介绍 在Django中, 模板(Templates)主要用于动态地生成HTML页面. 当需要基于某些数据(如用户信息, 数据库查询结果等)来动态地渲染HTML页面时, 就会使用到模板.以下是模板在Django中使用的几个关键场景: * 1. 动态内容生成: 当需要根据数据库中的数据或其他动态数据来生…

Hook 实现 Windows 系统热键屏蔽(二)

目录 前言 一、介绍用户账户控制&#xff08;UAC&#xff09; 1.1 什么是 UAC &#xff1f; 2.2 UAC 运行机制的概述 2.3 分析 UAC 提权参数 二、 NdrAsyncServerCall 函数的分析 2.1 函数声明的解析 2.2 对 Winlogon 的逆向 2.3 对 rpcrt4 的静态分析 2.4 对 rpcrt4…

240705_昇思学习打卡-Day17-基于 MindSpore 实现 BERT 对话情绪识别

240705_昇思学习打卡-Day17-基于 MindSpore 实现 BERT对话情绪识别 近期确实太忙&#xff0c;此处仅作简单记录&#xff1a; 模型简介 BERT全称是来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff0c…

14-32 剑和诗人6 - GenAI 重塑 SRE 和云工程实践

在不断发展的软件开发和运营领域&#xff0c;各种学科的融合催生了新的范式和实践&#xff0c;旨在简化流程、加强协作和推动创新。DevSecOps、站点可靠性工程 (SRE)、平台工程和云工程已成为支持现代软件系统的重要支柱&#xff0c;每个支柱都解决了独特的挑战和要求。 然而&…

Fastapi 项目第二天首次访问时数据库连接报错问题Can‘t connect to MySQL server

问题描述 Fastapi 项目使用 sqlalchemy 连接的mysql 数据库&#xff0c;每次第二天首次访问数据库相关操作&#xff0c;都会报错&#xff1a;sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, “Can’t connect to MySQL server on ‘x.x.x.x’ ([Err…

【Unity数据交互】Unity中使用二进制进行数据持久化

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 专栏交流&#x1f9e7;&…

2.4G无线收发芯片 XL2401D,SOP16封装,集成单片机,高性价比

XL2401D 芯片是工作在2.400~2.483GHz世界通用ISM频段&#xff0c;片内集成了九齐 NY8A054E单片机的SOC无线收发芯片。芯片集成射频收发机、频率收生器、晶体振荡器、调制解调器等功能模块&#xff0c;并且支持一对多组网和带ACK的通信模式。发射输出功率、工作频道以及通信数据…

vue3自定义全局指令和局部指令

1.全局指令 el&#xff1a;指令绑定到的DOM元素&#xff0c;可以用于直接操作当前元素&#xff0c;默认传入钩子的就是el参数&#xff0c;例如我们开始实现的focus指令&#xff0c;就是直接操作的元素DOM binding&#xff1a;这是一个对象&#xff0c;包含以下属性&#xff1a;…

Zynq系列FPGA实现SDI视频编解码,基于GTX高速接口,提供5套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案在Xilinx--Kintex系列FPGA上的应用 3、详细设计方案设计原理框图SDI 输入设备Gv8601a 均衡器GTX 解串与串化SMPTE SD/HD/3G SDI IP核BT1120转RGB图像缓存视频读取控制HDMI输出RGB转BT1120Gv8500 驱…

玩转云服务:Oracle Cloud甲骨文永久免费云服务器注册及配置指南

上一篇&#xff0c;带大家分享了&#xff1a;如何薅一台腾讯云服务器。 不过&#xff0c;只有一个月免费额度&#xff0c;到期后需要付费使用。 相对而言&#xff0c;海外云厂商更加慷慨一些&#xff0c;比如微软Azure、甲骨文、亚马逊AWS等。 甲骨文2019年9月就推出了永久免…

信用卡没逾期就万事大吉了吗?

6月28日&#xff0c;中国人民银行揭晓了《2024年第一季度支付体系概览》&#xff0c;数据显示&#xff0c;截至本季度末&#xff0c;信用卡及借贷合一卡的总量为7.6亿张&#xff0c;与上一季度相比&#xff0c;这一数字微降了0.85个百分点。同时&#xff0c;报告还指出&#xf…

华为OD机试 - 跳马 - 广度优先搜索BFS(Java 2024 D卷 200分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…

JMeter:循环控制器While Controller的用法小结

前言 在之前的博文“JMeter案例优化&#xff1a;测试执行结束后&#xff0c;实现tearDown的几种方式”中&#xff0c;尝试了JMeter的循环控制器While Controller&#xff0c;发现还有点小复杂&#xff0c;将学习过程记录下来&#xff0c;免得遗忘。 注&#xff1a;我使用的是…

【机器学习】机器学习与自然语言处理的融合应用与性能优化新探索

引言 自然语言处理&#xff08;NLP&#xff09;是计算机科学中的一个重要领域&#xff0c;旨在通过计算机对人类语言进行理解、生成和分析。随着深度学习和大数据技术的发展&#xff0c;机器学习在自然语言处理中的应用越来越广泛&#xff0c;从文本分类、情感分析到机器翻译和…

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

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

tobias实现支付宝支付

tobias是一个为支付宝支付SDK做的Flutter插件。 如何使用 你需要在pubspec.yaml中配置url_scheme。url_scheme是一个独特的字符串&#xff0c;用来重新启动你的app&#xff0c;但是请注意字符串“_”是不合法的。 在iOS端&#xff0c;你还需要配置并传入一个universal link。…

PCL 点云压缩算法-Octree空间分割算法

点云压缩 一、概述1.1 算法概念1.2 算法描述1.3 参数解释二、代码实现三、结果示例🙋 效果展示 一、概述 1.1 算法概念 Octree点云压缩算法:是一种用于表示三维空间中的点云数据结构。它将空间划分为一个八叉树,每个节点可以有最多八个子节点,代表了一个正方形的子空间…

jenkins学习

一、jenkins介绍 1.介绍 Jenkins 是一款流行的开源持续集成&#xff08;Continuous Integration&#xff09;工具&#xff0c;广泛用于项目开发&#xff0c;具有自动化构建、测试和部署等功能 2.特点 开源的Java语言开发持续集成工具&#xff0c;支持持续集成&#xff0c;持…

逻辑这回事(八)---- 时钟与复位

时钟设计总结 时钟和复位是FPGA设计的基础&#xff0c;本章总结了一些逻辑时钟复位设计、使用中出现的问题&#xff0c;给出了设计要点&#xff0c;避免后续问题重犯。时钟和复位&#xff0c;本文都先从板级谈起&#xff0c;再到FPGA芯片级&#xff0c;最后到模块级别。仅在此…