Mybatis(3)

Mybatis

1、日志

1.1 日志工厂

如果一个数据库操作,出现了异常,需要排错。日志是最好的帮手!

在这里插入图片描述

  • SLF4J
  • LOG4J (需要掌握)
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING (掌握)
  • NO_LOGGING

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

STDOUT_LOGGING: 标准日志输出

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

在这里插入图片描述

输出的日志:
在这里插入图片描述

1.2 Log4j

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

第一步 :导入依赖

加入log4j-1.2.8.jar(可以选择log4j的更高版本)到lib下。

如果使用maven项目,也可以选择在pom.xml中新增依赖:

<!-- 加入log4j支持 -->

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.17</version>

</dependency>

第二步: 配置文件
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
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/kuang.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
第三步: 设置映射

在这里插入图片描述

第四步 : 启动测试
[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[org.apache.ibatis.io.VFS]-Class not found: org.jboss.vfs.VFS
[org.apache.ibatis.io.JBoss6VFS]-JBoss 6 VFS API is not available in this environment.
[org.apache.ibatis.io.VFS]-Class not found: org.jboss.vfs.VirtualFile
[org.apache.ibatis.io.VFS]-VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
[org.apache.ibatis.io.VFS]-Using VFS adapter org.apache.ibatis.io.DefaultVFS
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1772160903.
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a10787]
[com.lei.dao.UserDao.getUserByid]-==>  Preparing: select * from mybatis.user where id =? 
[com.lei.dao.UserDao.getUserByid]-==> Parameters: 3(Integer)
[com.lei.dao.UserDao.getUserByid]-<==      Total: 1
User{id=3, name='王五', password='123456'}
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a10787]
[org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@69a10787]
[org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 1772160903 to pool.

Process finished with exit code 0

2、分页

分页的好处

  • 减少数据的处理量

2.1使用Limit分页

select  * from  user  limit  0,2
一页 显示两个数据 从第0个开始查

使用Mybatis实现分页

接口:

 //分页
List<User>  getuserlimit(Map<String,Object> map);

Mapper.xml

<select id="getuserlimit"  parameterType="map"  resultMap="USERS">
    select  * from  mybatis.user limit ${start} , ${ends}
</select>

测试类

@Test
public  void  test7(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserDao mapper = sqlSession.getMapper(UserDao.class);
    Map hashMap = new HashMap();
    hashMap.put("start",0);
    hashMap.put("ends",3);
    List getuserlimit = mapper.getuserlimit(hashMap);
    System.out.println(getuserlimit.toString());
    sqlSession.close();

}

2.2 RowBounds分页

不使用SQL语句分页

接口:

//RowBounds分页
 List<User>  getUserByRowBounds(); 

Mapepr.xml

<select id="getUserByRowBounds" resultMap="USERS">
    select  * from  mybatis.user
</select>

测试类

@Test
public  void  test8(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    //通过 RowBounds实现分页
    RowBounds rowBounds = new RowBounds(0,2);
    List <User> objects = sqlSession.selectList("com.lei.dao.UserDao.getUserByRowBounds", null, rowBounds);
    System.out.println(objects.toString());
}

3、 使用注解开发

底层核心:使用反射机制

1.注解:在接口上实现

在注解中写SQL语句

//使用注解开发
@Select("select * from user")
List<User>  getUsers();

2.在核心配置文件中绑定接口

<mappers>
    <mapper resource="com/lei/dao/UserMapper.xml"/>
    <mapper class="com.lei.dao.UserDao"></mapper>
</mappers>

本质:反射机制实现

底层:动态代理!

在这里插入图片描述

4、Mybatis执行流程刨析

第一步:通过Resources获取加载全局配置文件

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);

第二步:实例化SqlSessionFactoryBuilder构造器

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

**第三步:解析配置文件流 **

public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
}

在这里插入图片描述

返回一个Configuration对象 里面有所有的配置信息

第四步:实例化SqlSessionFactory

事务管理器

第五步:创建执行器Executor

第六步:创建SqlSession

第七步:实现CRUD

执行成功提交事务 执行失败事务回滚到书屋管理器
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

5、使用注解CRUD

我们可以在工具类创建的时候自动提交事务

public  static SqlSession getSqlSession() {
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
      return sqlSession;
}

编写接口 增加注解

 @Select("select * from user where id= #{id}")
 User getUserByID  ( @Param("id") int id);
 
 //更新
@Update("update  user set name=#{name} ,pwd=#{password} where id=#{id}")
  int updateUser (User user);
  
//删除
 @Delete("delete from user where id=#{id}")
 int deleteuser (@Param("id") int id);

注意:必须将接口绑定到核心注册文件中

在这里插入图片描述

关于@Param()注解

  • 基本类型的参数或者Sting类型的参数需要加上@Param
  • 引用类型不需要加
  • SQL语句中引用的值就是注解中的值

#{} 和 ${}的区别

  • #{} 为预编译 防止SQL注入

6、Lombok

Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。

常用注解:

@Setter :注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。

@Getter :使用方法同上,区别在于生成的是getter方法。

@ToString :注解在类,添加toString方法。

@EqualsAndHashCode: 注解在类,生成hashCode和equals方法。

@NoArgsConstructor: 注解在类,生成无参的构造方法。

@RequiredArgsConstructor: 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。

@AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。

@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。

@Slf4j: 注解在类,生成log变量,严格意义来说是常量。

减少实体类的代码量

7、多对一的处理

在这里插入图片描述

  • 多个学生 一个老师

  • 学生角度 :多对一 多个学生拥有共同的一个老师

  • 老师角度:一对多 同一个老师拥有很多学生
    在这里插入图片描述

    SQL:

    CREATE TABLE teacher (
    
    id INT(20)  NOT NULL,
    
    name VARCHAR(20) DEFAULT NULL,
    
    PRIMARY KEY (id)
    
     ) 
    
     ENGINE = INNODB DEFAULT CHARSET = utf8;
    
     INSERT INTO teacher (id,name)  VALUES (1,'马老师')
    
    
    
    CREATE TABLE student(
    
    id  INT(20) NOT NULL,
    
    name VARCHAR (20) DEFAULT NULL,
    
    tid INT(10) DEFAULT NULL,
    
    PRIMARY KEY (id),
    
    KEY fktid (tid),
    
    CONSTRAINT fktid FOREIGN KEY (tid) REFERENCES teacher (id)
    
    )
    
    ENGINE = INNODB DEFAULT CHARSET = utf8;	
    
    INSERT INTO student (id,name,tid) VALUES ('1','小张','1');
    
    INSERT INTO student (id,name,tid) VALUES ('2','小王','1');
    
    INSERT INTO student (id,name,tid) VALUES ('3','小李','1');
    
    INSERT INTO student (id,name,tid) VALUES ('4','小马','1');
    
    INSERT INTO student (id,name,tid) VALUES ('5','小邓','1');
    
    

测试环境搭建

1.导入lombok

2.新建实体类Teacher,Student

public class Student {
    private  int id;
    private  String name;
    //学生关联一个老师
    private  Teacher teacher;
public class Teacher {
    private  int id;
    private  String name;

3.建立Mapper接口

4.建立Mapper.xml文件

5.在核心配置文件中绑定注册我们的Mapper接口或者文件

在这里插入图片描述

按照查询嵌套处理
<select id="getStudent"  resultMap="StudentTeacher">
   select * from mybatis.student
</select>
<resultMap id="StudentTeacher" type="Student">
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"></association>
</resultMap>
<select id="getTeacher" resultType="Teacher">
    select  * from  mybatis.teacher where id=#{tid}
</select>
先查询 学生的tid
再根据tid查询对应的老师

在这里插入图片描述

按照结果嵌套查询

查询出所有结果 再一一映射

<select id="getStudent2" resultMap="StudentTeacher2">
    select  s.id  sid  , s.name sname ,t.name tname from student s , teacher t
    where  s.tid =t.id
 </select>
<resultMap id="StudentTeacher2" type="Student">
    <result property="id" column="sid"></result>
    <result property="name" column="sname"></result>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"></result>
    </association>

</resultMap>

在这里插入图片描述

8、一对多的处理

比如:一个老师拥有多个学生!

对于老师而言,就是一对多的关系!

1.环境搭建

public class Student {
    private  int id;
    private  String name;
    private  int tid ;
public class Teacher {
    private  int id;
    private  String name;
    //一个老师包含多个学生
    private List<Student> student;

按照结果嵌套查询

<select id="getTeacher" resultMap="StudentTeacher">
select s.id sid ,s.name sname,t.id tid,t.name tname from student s, teacher t
where  s.tid=t.id  </select>
<resultMap id="StudentTeacher" type="Teacher">
    <result property="id" column="tid"></result>
    <result property="name" column="tname"></result>
    <collection property="student" ofType="Student">
        <result property="id" column="sid"></result>
        <result property="name" column="sname"></result>
    </collection>
</resultMap>

在这里插入图片描述

小结

1.关联 : 多对一

2.集合 一对多

面试高频

  • Mysql引擎
  • innoDB底层原理
  • 索引
  • 索引优化!

9、动态SQL

什么是动态SQL:动态SQL就是根据不同的条件生成不同的SQL语句
在这里插入图片描述

环境搭建

创建一个基础工程

1.导包

2.编写配置文件

3.编写实体类
在这里插入图片描述

4.编写实体类对应的Mapper接口和xml
在这里插入图片描述

if

<select id="findActiveBlogWithTitleLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

这条语句提供了可选的查找文本功能。如果不传入 “title”,那么所有处于 “ACTIVE” 状态的 BLOG 都会返回;如果传入了 “title” 参数,那么就会对 “title” 一列进行模糊查找并返回对应的 BLOG 结果

如果不传入title参数 就不会执行if语句里面的模糊查询 会返回所有的BLOG 如果传入title 执行模糊查询 实现动态SQL语句

<select id="selectBlogIF" parameterType="map" resultType="Blog">
    select * from  mybatis.blog where 1=1
    <if test="title!=null">
        and  title=#{title}
    </if>
  <if test="author!=null">
      and author=#{author}
  </if>
</select>

不传入title 和author的查询结果

返回了所有BIOG

在这里插入图片描述

传入参数后的查询结果

在这里插入图片描述

if就相当于一个动态的条件判断语句

常用标签

choose、when、otherwise

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

choose就是只匹配一个条件语句只执行 只走一个条件。

mapper写法:

<select id="ChooseBlog" parameterType="map" resultType="Blog">
    select  * from  mybatis.blog
    <where>
    <choose>
        <when test="title!=null">
            and title = #{title}
        </when>
        <when test="author!=null">
            and  author = #{author}
        </when>
        <otherwise>
            and  views=#{views}
        </otherwise>
    </choose></where>
</select>

测试语句:

@org.junit.Test
    public  void test3 (){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    Map  map = new HashMap ();
    map.put("title","金城武");
    List <Blog> blogs = mapper.ChooseBlog(map);
    System.out.println(blogs.toString());
    sqlSession.close();
}

查询结果
在这里插入图片描述

where、set

<update id="updateBlog" parameterType="map" >
    update  mybatis.blog
    <set>
        <if test="title!=null">
            title=#{title},
        </if>
        <if test="author!=null">
            author =#{author}
        </if>
        where  id=#{id}
    </set>
</update>

动态SQL 本质还是SQL语句 , 不过可以执行一些逻辑代码

SQL片段

把公共的SQL语句 抽取出来 方便代码复用

使用sql标签

<sql id="if-title-author">
    <if test="title!=null">
        and  title=#{title}
    </if>
    <if test="author!=null">
        and author=#{author}
    </if>
</sql>

在其他语句中引用这个片段

使用include标签 引用SQL片段

在这里插入图片描述

Foreach

遍历查询
在这里插入图片描述

<select id="ForeachBlog" parameterType="map" resultType="Blog">
  select * from mybatis.blog
  <where>
      <foreach collection="ids" item="id" open="and(" close=")" separator="or"></foreach>
      id=#{id}
  </where>  
</select>
   public  void  test5(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    Map map = new HashMap();
    ArrayList<Integer> ids =new ArrayList <Integer>();
    map.put("ids",ids);
    List <Blog> blogs = mapper.ForeachBlog(map);
    for (Blog blog : blogs) {
        System.out.println(blogs.toString());
    }
    sqlSession.close();
}

10、缓存

10.1简介

将查询过的结果暂存在内存中,当我们再次查询相同数据时 ,直接在缓存中查询!

  • 存在内存中的临时数据
  • 将用户经常查询的数据放在缓存中 以便二次查询 减少资源消耗
  • 减少与数据库的互动次数,减少系统开销
  • 适用于经常查询且不经常改变的数据【可以使用缓存】

10.2Mybatis 缓存

  • MyBatis 包含一个非常强大的查询缓存特性,他可以非常方便地定制和配置缓存,缓存可以极大的提升查询效率

  • MyBatis 系统中默认定义了两级缓存:一级缓存二级缓存

  • 默认情况下,只有一级缓存开启,(SqlSession级别的缓存,也称为本地缓存)

  • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。

  • 为了提高扩展性,Mybatis定义了缓存接口Cache。我们可以通过实现Cache接口来定义二级缓存

    10.3 一级缓存

    存在于一个sqlsession中 默认是开启的

    增删改操作会刷新缓存

在这里插入图片描述

10.4 二级缓存

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个命名空间,对应一个二级缓存
  • 工作机制
    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了,但是我们想要的是,会话关闭了 一级缓存中的数据会被保存到二级缓存中去
    • 新的会话查询信息,就可以从二级缓存中获取内容
    • 不同的mapper查处的数据会放在自己对应的缓存中

步骤:

1.开启全局缓存

在这里插入图片描述

2.在要使用二级缓存的Mapper中开启

<mapper namespace="com.lei.dao.BlogMapper">
    <cache >
    </cache>
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值