飞道的博客

Mybatis学习

409人阅读  评论(0)


前言

今天正式开始学习SSM框架,首先学习Mybatis框架


提示:以下是本篇文章正文内容,下面案例可供参考

一、MyBatis是什么?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

二、第一个Mybatis程序

1.在maven项目的pom.xml文件中引入MyBatis依赖

代码如下:

<dependencies>
        <dependency>
            <!--引入数据库依赖-->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <!-- 引入Mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- 引入Junit依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.在resource中配置核心文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
<-- 默认环境 !-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>

3.设置工具类

从 XML 中构建 SqlSessionFactory,每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
三句代码固定的:
String resource = “org/mybatis/example/mybatis-config.xml”;
InputStream inputStream =
Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(inputStream);

private static SqlSessionFactory sqlSessionFactory;
    static {
   
        try {
   
            //获取sqlSessionFactory对象
            //每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的
            String resource="mybatis-config.xml";
            InputStream resourceAsStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        } catch (IOException e) {
   
            e.printStackTrace();
        }
    }
 /*
    * 有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    * SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
    * 你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
    * */
    //获得sqlSession对象
    public static SqlSession getSqlSession(){
   
        return sqlSessionFactory.openSession();
    }

三、CURD

1.创建实体类与编写和实体类对应的接口

首先建出和数据库中的表对应的实体类
然后在Dao包中编写类的接口

Mapper(映射器)就是原来的Dao
在resources中编写与接口绑定的xml文件,相当于是接口的实现类
Mapper包中的实体类接口

public interface UserMapper {
   
    //获取全部用户信息
    public List<User> getUserList();
    //根据用户Id获取用户信息
    public User getUserById(int id);
    //插入用户
    public int addUser(User user);
    //修改用户
    public int updateUser(User user);
    //删除用户
    public int deleteUser(int id);
    //模糊查询
    public List<User> getUserLike(String value);

}

2.创建实体类对应的接口的xml文件

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.night.Mapper.UserMapper">
    <select id="getUserList" resultType="com.night.pojo.User">
            select * from mybatis.user
    </select>
    <select id="getUserById" parameterType="int" resultType="com.night.pojo.User">
        select * from mybatis.user where id=#{
   id}
    </select>
    <insert id="addUser" parameterType="com.night.pojo.User">
        insert into mybatis.user(id,name,password) values (#{
   id},#{
   name},#{
   password})
    </insert>
    <update id="updateUser" parameterType="com.night.pojo.User">
        update mybatis.user set name=#{
   name},password=#{
   password} where id=#{
   id};
    </update>
    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{
   id}
    </delete>
    <select id="getUserLike" resultType="com.night.pojo.User">
        select *
        from mybatis.user where name like #{
   value};
    </select>
</mapper>

并在核心配置文件config.xml中引入

    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>

注意:

如果是在Mapper包中写的xml文件,需要在pom.xml文件中添加以下配置。

<build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
        </resources>
    </build>

接口绑定xml文件,相当于是接口的实现类
在xml文件中实现 Sql语句的编写
注意:
xml文件中的namespace中的包名,要和Mapper(原来的Dao)接口的包名一样

1.select标签:

选择,查询语句

id :就是对应的namespace中的方法名
resultType:sql语句执行的返回值
parameterType:参数类型
    <select id="getUserById" parameterType="int" resultType="com.night.pojo.User">
        select * from mybatis.user where id=#{
   id}
    </select>

2.测试代码:

在写测试代码时,这两句代码不变

SqlSession sqlSession = MybatisUtils.getSqlSession();
/*
其他代码
*/
sqlSession.close();

sqlSession用完后一定要关闭,不然会很浪费资源

3.增删改需要提交事务:

//增删改需要提交事务
    @Test
    public void test3() {
   
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapperAdd = sqlSession.getMapper(UserMapper.class);
        int i = mapperAdd.addUser(new User(4, "赵六", "000000"));
        if(i>0){
   
            System.out.println("插入成功");
        }
        //提交事务
        sqlSession.commit();
        sqlSession.close();
    }

也可以在工具类返回SqlSession的方法中设置自动提交事务

//这样SqlSession会自动提交事务
public static SqlSession getSqlSession(){
   
        return sqlSessionFactory.openSession(true);
    }

假设实体类或者数据库中的表、字段或者参数过多,可以用map作为参数

HashMap<String, Integer> map = new HashMap<>();
        map.put("startIndex",0);
        map.put("pageSize",2);
        List<User> userByLimit = mapper.getUserByLimit(map);

四、配置解析

1.核心配置文件mybatis-config.xml

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

注意:
各个属性的插入顺序必须严格按照这个顺序来,不然会报错

1.环境配置:

尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。

<-- 环境的默认选择!-->
<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <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>

1.事务管理器(transactionManager)

mybatis中有两种默认的事务管理器:JDBC、MANAGED

2.数据源(dataSource):

有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]")

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

2.属性

创建db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456

注意!!!:

在写db.properties时,url的路径和在核心配置文件中的写法不一样
核心配置文件中的写法为:

"jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"

有转义符&

而db.properties中的写法为:

jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8

这些属性可以在外部进行配置,并可以进行动态替换。

   <!--从外部引入资源,可以动态的进行替换-->
    <properties resource="db.properties"></properties>
<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <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>
  • 可以介质引入外部文件
  • 可以在其中增加一些属性配置
  • 如果两个文件中有同一个字段,优先匹配属性外的。

3.类型别名:

型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。

例如以前:

resultType="com.company.pojo.User"

可以给实例类起别名
1.在config.xml文件中配置:

<typeAlias type="com.company.pojo.User" alias="User"></typeAlias>

2.也可以指定一个包名,Mybatis会在包名下面搜索需要的Java Bean,比如:扫描实体类的包,它的默认别名就为这个类的别名,首字母小写

<typeAliases>
  <package name="com.company.pojo"/>
</typeAliases>

3.映射器(mappers)

MapperRegistry:注册绑定我们的Mapper文件:

1.使用相对于类路径的资源引用
(推荐使用)(都在resourese目录下)目录间是斜杠不是点

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

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

<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>

3.使用映射器接口实现类的完全限定类名
(推荐使用)需要将xml文件与接口放在同一个包下

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

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

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

注意点:

接口和它的Mapper配置文件必须同名
接口和它的Mapper配置文件必须在同一个包下

4.生命周期与作用域

生命周期和作用域是至关重要的,因为错误的使用会导致很严重的并发问题

SqlSessionFactoryBuilder:
一旦创建了SqlSessionBuilderFactory,就不需要它了
作用范围最好是局部变量

SqlSessionFactory:
说白一点就可以想象为:数据库连接池
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或者重新创建另一个实例
因此SqlSessionFactory的最佳作用域就是应用作用域
最简单的就是使用单例模式或者静态单例模式

SqlSession:
连接到连接池的一个请求
SqlSession的实例不是线程安全的,因此是不能被共享的,所以他的最佳作用域是请求或者方法作用域
用完之后要赶紧关闭,否则资源要被占用

5.resultmap结果集映射

1.解决属性名和字段名不一致的问题

当实体类中的属性名与数据库中的字段名不一样时
在执行一些增删查改的操作时,会造成一些故障。
如查询的时候:
这是因为,在.xml文件中的查询语句

select * from mybatis.user where id=#{
   id}

实际上是:

select id,name,password from mybatis.user where id=#{
   id}

此时的password和pwd并不相同,以至于让返回的密码值为空
解决方法:
1.取别名:
…paaword as pwd…
2.resultMap:结果集映射
用resultMap让数据库中的字段与实体类的属性一一对应,并不需要名字一样

column:数据库中的字段 property:实体类中的属性

 <resultMap id="UserMap" type="User">
        <!-- column:数据库中的字段  property:实体类中的属性-->
        <result column="id" property="id"></result>
        <result column="name" property="name"></result>
        <result column="password" property="pwd"></result>
    </resultMap>
    <select id="getUserById" parameterType="_int" resultMap="UserMap">
        select * from mybatis.user where id=#{
   id}
    </select>
  • resultMap 元素是 MyBatis 中最重要最强大的元素。
  • ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

其实只需要映射不一样的字段

五.日志

5.1.日志工厂

如果一个数据库操作引起了异常,我们需要排错。日志就是最好的助手
**logImpl :**指定Mybatis创建具有延迟加载能力的对象所用到的代理工具

在Mybatis中具体使用哪个日志实现,在设置中设定:

SLF4J

LOG4J

LOG4J2

JDK_LOGGING

COMMONS_LOGGING

STDOUT_LOGGING (掌握)

NO_LOGGING

STDOUT_LOGGING标准日志输出

5.2.设置日志

在Mybatis核心文件中,配置我们的日志

严格遵循顺序

configuration(配置)

properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
<!--设置日志-->
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/> <!--name和value的值不能乱加空格和乱改,很严格-->
</settings>

注意:
name和value的值不能乱加空格和乱改,很严格

5.2.1日志文件Log4j:

1.什么是log4j:

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等
我们也可以控制每一条日志的输出格式
通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程
可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码

2.在pom.xml文件中先导入Log4j的包

<dependency>

   <groupId>log4j</groupId>

   <artifactId>log4j</artifactId>

   <version>1.2.17</version>

</dependency>

3.在resourse目录下创建log4j.properties

log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/night.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{
   yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

4.配置log4j的实现

<setting name="logImpl" value="LOG4J"/>

5.Log4j的使用,测试运行

简单使用:

1.导入log4j.logger的包

2.获取日志对象,参数为当前类的class

3.日志级别

info\debug\error

六.分页:

分页是为了减少数据的处理量

关键字:(limit)

select * from user limit 0,2;

select * from user limit 起始序号,每页数量

1.使用Mybatis实现分页

1.接口;

//分页查询
public List<User> getUserByLimit(Map<String,Integer> map);

2.Mapper.xml

<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
    select * from mybatis.user limit #{
   startIndex},#{
   pageSize}
</select>

3.测试:

HashMap<String, Integer> map = new HashMap<>();
map.put("startIndex",0);
map.put("pageSize",2);
List<User> userByLimit = mapper.getUserByLimit(map);

RowBounds分页与limit分页的区别:

RowBounds是逻辑分页,limit是物理分页

七.注解开发:

在使用简单的sql语句时进行数据库操作时,可以使用注解开发,这样会减少代码量

1.用法:

在接口方法的前面使用注解,注解内容就是sql语句。

@Select("select * from mybatis.user")
public List<User> getUserList();

方法存在多个参数,所有参数前面必须加上@Param注解

注解的参数名需要和语句里的参数名一致,可以和参数名不一样

@Select("select * from mybatis.user where id=#{id2}")
public User getUserById(@Param("id2") int id);//  注解的参数名需要和语句里的参数名一致,可以和参数名不一样

不用再用xml文件实现sql语句

注意:使用注解实现增删改时,这里要改

//获得sqlSession对象,自动提交事务
public static SqlSession getSqlSession(){
   
    return sqlSessionFactory.openSession(true);

2.关于@Param()注解

基本类型的参数或者String类型,需要加上
引用类型不需要加上
如果只有一个基本类型,可以忽略,但建议加上
在SQL中引用的字段就是注解里的属性名

八、Lombok:

Lombok是一个插件,可以在实体类上用注解,自动写入其他方法

@Data 所有的getter 和setter方法
@AllArgsConstructor //有参构造
@NoArgsConstructor //无参构造

多对一查询:学生与老师

根据嵌套查询和子查询:

九、一对多和多对一小结:

关联:association(多对一)

集合:collection (一对多)

javaType 和 ofType

javaType:用来指定实体类中的属性

ofType:用来指定映射到List或者集合中的pojo类型,泛型中的约束类型

十、动态sql环境搭建:

导包、编写配置文件、编写实体类、编写Mapper接口和Mapper.xml文件

可以用UUID类生成唯一的ID:

动态sql环境搭建:

导包、编写配置文件、编写实体类、编写Mapper接口和Mapper.xml文件

如果数据库字段中有下划线,可以在配置文件中配置让字段名自动转换为驼峰命名

<setting name="mapUnderscoreToCamelCase" value="true"/>

可以用UUID类生成唯一的ID:

 return UUID.randomUUID().toString().replaceAll("-","");
}

1.动态SQL之if语句

可以根据传递的参数参查询不同的结果,只需要改变参数,而不需要改变Sql语句
动态SQL之if语句
可以根据传递的参数参查询不同的结果,只需要改变参数,而不需要改变Sql语句
使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列.
set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)

十一、Mybatis缓存:

1.一级缓存:

Mybatis默认的是一级缓存。

只需在MyBatis的配置文件中,添加如下语句,就可以使用一级缓存。共有两个选项,SESSION或者STATEMENT,默认是SESSION级别,即在一个MyBatis会话中执行的所有语句,都会共享这一个缓存。一种是STATEMENT级别,可以理解为缓存只对当前执行的这一个Statement有效。

<setting name="localCacheScope" value="SESSION"/>

一级缓存示意图:

缓存失效的情况:

1.查询不同的东西

2.增删查改操作,可能会改变原来的数据,所以必定会刷新缓存

3.查询不同的Mapper.xml

4.手动清理缓存 clearCache()方法

小结:一级缓存是默认开启的,只在一次SQLSession中有效,也就是拿到连接到关闭这个区间。

MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

2.二级缓存:

如果多个SqlSession之间需要共享缓存,则需要使用到二级缓存。

二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存被多个SqlSession共享,是一个全局的变量。

二级缓存的工具示意图:

当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

二级缓存配置:

1.在config.xml文件中设置二级缓存开启

<setting name="cacheEnabled" value="true"/>

在实体类接口的xml文件中配置:

cache这个标签可以设置其他参数:

<cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/>

eviction:代表的是缓存回收策略,目前MyBatis提供以下策略。
(1) LRU,最近最少使用的,一处最长时间不用的对象
(2) FIFO,先进先出,按对象进入缓存的顺序来移除他们
(3) SOFT,软引用,移除基于垃圾回收器状态和软引用规则的对象
(4) WEAK,弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象。这里采用的是LRU,
移除最长时间不用的对形象

    flushInterval:刷新间隔时间,单位为毫秒,这里配置的是100秒刷新,如果你不配置它,那么当
    SQL被执行的时候才会去刷新缓存。

    size:引用数目,一个正整数,代表缓存最多可以存储多少个对象,不宜设置过大。设置过大会导致内存溢出。
    这里配置的是1024个对象

    readOnly:只读,意味着缓存数据只能读取而不能修改,这样设置的好处是我们可以快速读取缓存,缺点是我们没有
    办法修改缓存,他的默认值是false,不允许我们修改

总结


转载:https://blog.csdn.net/qq_45468597/article/details/115640530
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场