mybatis --入坑指南

什么是mybatis?

  • 它支持定制化 sql 、储存过程以及高级映射,是一个持久层框架
  • 几乎避免了所有的 JDBC 代码和手动设置参数以及结果集
  • 使用简单的注解或者xml 来映衬原生类型、接口和java 的POJO

持久层

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转换的过程
    内存:断电及失

温馨提示:后面学习,记得 sqlSession.close () sqlSession.commit () 哦 ~~

基础

官网:https://mybatis.net.cn/

使用方法步骤如下所示:

①在 resource 中核心配置文件 mybatis-config.xml

url配置 = jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8&useSSL=false

<?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="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

②创建一个 Utils 类,获取sqlSessionFactory对象

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

③既然有了sqlSessionFactory的实例,顾名思义,我们也就可以获得 sqlSession的实例了。sqlSession 完全包含了面向数据库执行sql命令所需的所有的方法。

在这里插入图片描述

以下将案例中整体的代码展示如下图(重点用红色标记):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解决找不到resource下的xml文件
<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
纠结好久的问题

Mybatis中,返回一个多条数据(List)时,resultType的值指定的不是List,而是List中的元素类型

CRUD

namespace :要和对应的 Dao/mapper 接口一致
select 中的 id:就是对应的namespace中使用方法的方法名必须要保持一致
resultType:就是要返回的参数类型

案例如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

模糊查询 Map 万能(不正规的野路子)

假设,我们的实体类,或者数据库中的表,或者字段参数过多,我们应当考虑使用Map

代码演示如下(UserMapper、UserMapper.xml、mybatisTest):

void addUser2(Map<String,Object> key);
 <insert id="addUser2" parameterType="map" >
        insert into mybatisTest (id,name,pwd) values (#{uid},#{uname},#{upwd})
    </insert>
    public void addUser2(){
        SqlSession sqlSession = mybatisUtils.getSqlSession();
        UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);
        Map<String,Object> map = new HashMap<String,Object>();

        map.put("uid","8");
        map.put("uname","xjj");
        map.put("upwd","123");

        usersMapper.addUser2(map);

        sqlSession.commit();
        sqlSession.close();
    }
模糊查询

在这里插入图片描述

以上方法存在 sql 注入

推荐:
在这里插入图片描述

配置之属性优化

在这里插入图片描述

示例:
在这里插入图片描述
在这里插入图片描述
或者:
在这里插入图片描述
.
.
都可以。

别名 ⇒ typeAlises

方法一(实体类比较少建议):

在这里插入图片描述

在这里插入图片描述

方法二(实体类比较多的情况):

可以使用Bean的首字母小写的非限定类名来作为别名。
在这里插入图片描述

如果有注解,可以使用注解起别名。
在这里插入图片描述
在这里插入图片描述

Mappers

resource注册(推荐使用)

每一个Mapper都需要来注册

<Mappers>
	<Mapper resource="xxx.xml"/>
<Mappers>
class注册

每一个接口都必须来注册,并且,Mapper和配置文件必须同名同文件下才可

<Mappers>
	<Mapper class = " xxxMapper "/>
<Mappers>
name扫描包

Mapper和配置文件必须同名同文件下才可

<Mappers>
	<package name = "xxx"/>
</Mappers>
resultMap ⇒ 结果集映射

在这里插入图片描述

日志

在这里插入图片描述

在这里插入图片描述

log4j

①配置maven

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

②创建log4j.properites

百度查找 log4j 配置文件,很详细

### 设置Logger输出级别和输出目的地(控制台和文件夹) ###
log4j.rootLogger=debug, stdout,logfile

### 把日志信息输出到控制台 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
###控制台输出的格式为.err红色字体###
log4j.appender.stdout.Target=System.err
###控制台输出的布局方式###
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout

### 把日志信息输出到文件:jbit.log ###
log4j.appender.logfile=org.apache.log4j.FileAppender
### 设置输出文件夹的名字 ###
log4j.appender.logfile.File=jbit.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
### 自定义输出日志的格式 ###
log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}%l %F %p %m%n

#日志级别从高到低分为:
#A:off 最高等级,用于关闭所有日志记录。
#B:fatal 指出每个严重的错误事件将会导致应用程序的退出。
#C:error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
#D:warn 表明会出现潜在的错误情形。
#E:info 一般和在粗粒度级别上,强调应用程序的运行全程。
#F:debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
#G:all 最低等级,用于打开所有日志记录。

#Log4j提供的appender有以下几种:
#org.apache.log4j.ConsoleAppender(控制台),
#org.apache.log4j.FileAppender(文件),
#org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
#org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
#org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

# %d 输出日志时间点的日期或时间
# %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。
# %F: 输出日志消息产生时所在的文件名称 
# %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
# %m: 输出代码中指定的消息,产生的日志具体信息
# %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”

③配置log4j为日志实现
在这里插入图片描述

④使用log4j
在这里插入图片描述

分页

方法一:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法二:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

面相接口编程

官方案例:
在这里插入图片描述

个人测试:
在这里插入图片描述
在这里插入图片描述

  • 一般比较简单的可以这么写,但是这么写有局限性。比较复杂的话还是最好使用 XML 来配置。
  • 注解使用了反射机制。

注解的CRUD ⇒ 细节补充

我们可以在工具类创建的时候,自动创建事务。(俗称自动 sqlSession.commit() )
在这里插入图片描述

如果方法存在多个参数的时候,所有参数前面必须加上 @Param()。俗称,绑定参数。
在这里插入图片描述

参数中,#{id} (建议使用,不存在sql注入) 和 ${id} (不推荐,存在sql注入)

Lombok ⇒ (偷懒必备神器)⇒ 不推荐使用,但是灵活使用哦 ~~ 。

我们不用导入一些包了,可以用 Lombok 自动配置。

安装方法建议百度,那边更详细一点点。

  1. 在 Idea 安装插件
  2. 在项目中导入Jar包
  3. 使用@Getter、@Setter 、@Log4j 等常用的包/操作
    案例: @Data 会自动生成 get、set、toString、hashcode、equals 等方法。
    在这里插入图片描述

复杂环境搭建

对于学生这边而言,多个学生,关联一个老师【多对一】
对于老师这边而言,一个老师,关联多个学生【一对多】
在这里插入图片描述
在这里插入图片描述

多对一

遇到的问题:
在这里插入图片描述

这种情况下,怎么办呢 ?

① 按照查询嵌套处理(有问题,已经处理,在本小结的后面)

在这里插入图片描述
在这里插入图片描述

问题处理

在 id 为getTeacher 的 mysql 语句中,后面的 where id=#{id},中,id到底是哪一个呢?这个参数id是怎么传递下来的呢?解释如下图所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

向导①:同学们注意看,在查询这个 “mybatis02” 这个sql中,我们是有三个列的,分别是
id,name,teacher(int类型),我们再看②号向导映射的 Student 实体类 这张图,也有三个属性,id,name,teacher(Student属性)。

而 column 映射的是 向导① 中mysql中的 teacher(int类型的值),而引向的是下面的select,所以我们就可以直接用 mysql语句中的teacher值啦!

在这里插入图片描述

唠叨一句,请分清楚,什么是主表,什么是主映射哦 ~~

② 按照结果查询处理(已处理)

.
Pojo:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private int id;
    private String name;
    private Teacher teacher;
}

Interface:

public interface Students {

    // 多对一结果集映射
    List<Student> getStudent();

}

xml映射文件:

<!--    多对一结果集映射    -->
    <resultMap id="getTeacher" type="Test.Pojo.Student">
        <result column="sid" property="id" />
        <result column="sname" property="name" />
        <association property="teacher" javaType="Test.Pojo.Teacher">
            <result column="tname" property="name"></result>
            <result column="tid" property="id"></result>
        </association>
    </resultMap>

test:

    @Test
    public void test(){
        SqlSession sqlSession = new MybatisUtils().getSession();
        Students students = sqlSession.getMapper(Students.class);
        List<Student> stu = students.getStudent();
        for(Student s:stu){
           System.out.println(s.getId()+","+s.getName()+"-->"+s.getTeacher().getName());
        }
        sqlSession.close();
    }

在这里插入图片描述

遇到的问题

如图所示:

在这里插入图片描述

明明映射完 Teacher 直接用就可以,为什么还要 result 一个属性呢?
.
结论(个人观点):因为我们如果不写,就只告诉java我们需要映射Teacher类的一个模子 和 mysql 得出的值,并没有说将 mysql 的哪一个得出的值,映射到哪一个模子中的值里面去。所以,我们需要搭一下线。

一对多

结果集映射案例:

javaType 用来指定对象所属的 java 数据类型,也就是 private List <Post> posts 的 ArrayList 类型
ofType 用来指定对象的所属 javaBean 类,也就是尖括号的泛型 private Listposts

明白话:javatype 和 oftype 都是指代对象类型的,但是 javaType 是用来指待 Pojo 中的属性类型,而 ofType 指定的是映射到 list 集合属性中的 pojo 类型。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

实战:
在这里插入图片描述

子查询

在这里插入图片描述
在这里插入图片描述

动态SQL

什么是动态SQL?动态SQL就是根据不同的条件生成不同的SQL。

实例:
在这里插入图片描述

动态 IF 语句

例子已经摆出来啦~~
我们可以看到第三张图,这边是 IF 的使用方式咯 ~~ 同学可以研究一下下~~

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

遇到的问题(我可是解决了老半天嘞,快让我装个x)

先看错误示例:
在这里插入图片描述
我在教程上看到的是这个样子的代码,但是怎么测试,都报错,图如下
在这里插入图片描述
这个问题其实就是接收不到 name 参数,我们可以手动引导一下。

还有就是 new Hashmap 在创建的时候,传递 “name” 属性有可能会乱码,具体解决请百度哟 ~~。

choose / where / otherwise ⇒ 必须至少传递这个值(限制条件)

在这里插入图片描述

choose

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

set

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

trim:可以去百度了解一下,还是很实用的!

摘抄狂神笔录:所谓的动态sql,本质上还是sql语句,只是我们可以在sql的层面上去执行一个逻辑代码

forEach

可以百度一下,不经常使用。一般还是 where 等比较多。

+1

缓存

重点: 二级缓存的使用条件 ⇒ 一级缓存结束 或者 提交(转存)(同一个mapper下有效)

查询:需要链接数据库 ⇒ 比较消耗资源
一次性查询的结果,给他暂时存放到一个可以直接取到的地方! ⇒ 内存:缓存
我们再次查询数据的时候,直接走缓存,就不用去走数据了。(可以解决高并发系统的性能问题)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用二级缓存

开启缓存
  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;

工作机制

  • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中。如果当前会话关闭了,这个会话对应的一级缓存就没了。但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中,新的会话查询信息,就可以从二级缓存中获取内容;
  • 不同的mapper查出的数据会放在自己对应的缓存(map)中;

在这里插入图片描述
在这里插入图片描述

使用缓存

在这里插入图片描述

使用测试展示:

在这里插入图片描述

自定义(Ehcache)⇒ 用的人逐渐变少,可以去百度了解,先不用深究。

此处略,本人没学习,各位需要的小伙伴自己去百度吧。

完结撒花。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值