Mybatis

Posted tomcatist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis相关的知识,希望对你有一定的参考价值。

环境:

  • JDK1.8

  • mysql 5.7

  • maven 3.6.1

  • IDEA

回顾:

  • JDBC

  • Mysql

  • java基础

  • Maven

  • Junit

 

SSM框架:配置文件的:最好的方式:看官网文档;

1、简介

1.1、什么是Mybatis

技术图片

  • MyBatis 是一款优秀的持久层框架

  • 它支持定制化 SQL、存储过程以及高级映射

  • MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集

  • MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

  • MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。

  • 2013年11月迁移到Github。

 

如何获得Mybatis?

1.2、持久化

数据持久化

  • 持久化就是将程序的数据在持久状态瞬时状态转化的过程;

  • 内存:断电即失

  • 数据库(jdbc)io文件持久化。

  • 生活中:冷藏、罐头。

为什么需要持久化?

  • 有一些对象不能让他丢掉;

  • 内存太贵了;

1.3、持久层

Dao层、Service层、Controller层...

  • 完成持久化工作的代码层;

  • 层:界限十分明显;

1.4、为什么需要Mybatis?

  • 帮助程序员将数据存入到数据库中

  • 方便

  • 传统的JDBC代码太复杂了,简化

  • 不用Mybatis也可以,但Mybatis更容易上手。

  • 有点:

    • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

    • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。

    • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。

    • 提供映射标签,支持对象与数据库的orm字段关系映射

    • 提供对象关系映射标签,支持对象关系组建维护

    • 提供xml标签,支持编写动态sql。

最重要的一点:使用的人多

2、第一个Mybatis程序

思路:搭建环境--->导入Mybatis--->编写代码--->测试!

2.1、搭建环境

  • 搭建数据库

  • 新建项目:

  1. 新建一个普通Maven项目

  2. 删除src目录

  3. 导入maven依赖

<!--       Mysql驱动-->
       <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>8.0.18</version>
       </dependency>
?
       <!--       Mybatis-->
       <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis</artifactId>
           <version>3.5.3</version>
       </dependency>
?
<!--Junit-->
       <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
       <dependency>
           <groupId>org.junit.jupiter</groupId>
           <artifactId>junit-jupiter-api</artifactId>
           <version>5.5.2</version>
           <scope>test</scope>
       </dependency>
<?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.jdbc.Driver"/>
               <property name="url" value="jdbc:mysql://120.79.15.118:3306/test_sql?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
               <property name="username" value="test"/>
               <property name="password" value="123"/>
           </dataSource>
       </environment>
   </environments>
?
</configuration>
//从SqlSessionFactory拿到SqlSession
public class MybatisUtils {
   private static SqlSessionFactory sqlSessionFactory;//提升作用域
   static {
       String resource "mybatis-config.xml";
       InputStream inputStream null;
       try {
           //使用mybatis第一步:获取SqlSessionFactory对象
           inputStream Resources.getResourceAsStream(resource);
      } catch (IOException e) {
           e.printStackTrace();
      }
       SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);
?
  }
   
   //既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
   // SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
   
   public static SqlSession getSqlSession(){
       return sqlSessionFactory.openSession();
       
  }
}
package com.yuan.pojo;
//实体类
public class User {
   private int id;
   private String name;
   private String pwd;
?
   public User() {
  }
?
   public User(int id, String name, String pwd) {
       this.id id;
       this.name name;
       this.pwd pwd;
  }
?
   public int getId() {
       return id;
  }
?
   public void setId(int id) {
       this.id id;
  }
?
   public String getName() {
       return name;
  }
?
   public void setName(String name) {
       this.name name;
  }
?
   public String getPwd() {
       return pwd;
  }
?
   public void setPwd(String pwd) {
       this.pwd pwd;
  }
?
   @Override
   public String toString() {
       return "User{" +
               "id=" id +
               ", name=‘" name ‘‘‘ +
               ", pwd=‘" pwd ‘‘‘ +
               ‘}‘;
  }
}
public interface UserDao {
?
   List<UsergetUserList();
?
}
<?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:绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.yuan.dao.UserDao">
?
<!--   select 查询语句-->
   <select id="getUserList" resultType="com.yuan.dao.User">//写泛型内的User
      select * from mybatis.user
   </select>
?
</mapper>
<!--   每一个Mapper.xml都需要在Mybatis的核心配置文件中注册-->
   <mappers>
       <mapper resource="com/yuan/dao/UserMapper.xml"/>
   </mappers>
<!--   在build中配置resources,来防止我们资源导出失败的问题-->
   <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>
public class UserDaoTest {
?
   @Test
   public void test(){
?
?
       //第一步:获取sqlSession对象
       SqlSession sqlSession MybatisUtils.getSqlSession();
       //执行SQL
       //方式一:getMapper
       UserDao mapper sqlSession.getMapper(UserDao.class);
       List<UseruserList mapper.getUserList();
?
       for (User user : userList) {
           System.out.println(user);
?
      }
       //关闭sqlSession
       sqlSession.close();
  }
}
//根据id查询用户
User getUserById(int id);
?
<select id="getUserById" parameterType="int"
resultType="com.yuan.pojo.User">
select * from mybatis.user where id = #{id}
</select>
@Test
public void getUserById(){
   SqlSession sqlSession MybatisUtils.getSqlSession();
   
   UserMapper mapper sqlSession.getMapper(UserMapper.class);
   
   User user mapper.getUserById(1);
   
   System.out.println(user);
   
   sqlSession.close();
}
<insert id="addUser" parameterType="User"><br>  
  Insert into user(id,name,level,phone) values(#{id},#{name},#{level},#{phone});
   </insert>
<update id="updateUser" parameterType="User">
  update user set name=#{name},level=#{level},phone=#{phone} where id=#{id};
   </update>
<delete id="deleteUser" parameterType="User">
  delete from user where id=#{id};
   </delete>
sqlSession.commit();
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
driver = com.yuan.jdbc.Driver
url=jdbc:mysql://120.79.15.118:3306/test_sql?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=test
password=123
//引入外部配置文件
   <properties resource="db.properties">
       <property name="username" value="test"/>
       <property name="pwd" value="11111"/>
   </properties>
//可以给实体类起别名
   <typeAliases>
       <typeAlias type="com.yuan.pojo.User" alias="USER"/>
   </typeAliases>
  //可以给实体类起别名
   <typeAliases>
       <package name="com.yuan.pojo"/>
   </typeAliases>
@Alias("author")
public class Author {
  ...
}
idnamepwd (数据库)
idnamepassword  (实体类)
<!--   结果集映射-->
   <resultMap id="UserMap" type="User">
<!--       column:数据库中的字段 property:实体类中的属性 -->
       <result column="id" property="id"/>
       <result column="name" property="name"/>
       <result column="pwd" property="password"/>
   </resultMap>
   
   <select id="getUserById" resultMap="UserMap">
      select * from mybatis.user where id = #{id}
   </select>
?
<settings>
       <setting name="logImpl" value="STDOUT_LOGGING"/>
   </settings>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-core</artifactId>
   <version>2.12.1</version>
</dependency>
?
?
### 配置根 ###
log4j.rootLogger = debug,console ,fileAppender,dailyRollingFile,ROLLING_FILE,MAIL,DATABASE
?
### 设置输出sql的级别,其中logger后面的内容全部为jar包中所包含的包名 ###
log4j.logger.org.apache=dubug
log4j.logger.java.sql.Connection=dubug
log4j.logger.java.sql.Statement=dubug
log4j.logger.java.sql.PreparedStatement=dubug
log4j.logger.java.sql.ResultSet=dubug
?
### 配置输出到控制台 ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
?
### 配置输出到文件 ###
log4j.appender.fileAppender = org.apache.log4j.FileAppender
log4j.appender.fileAppender.File = logs/log.log
log4j.appender.fileAppender.Append = true
log4j.appender.fileAppender.Threshold = DEBUG
log4j.appender.fileAppender.layout = org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
?
### 配置输出到文件,并且每天都创建一个文件 ###
log4j.appender.dailyRollingFile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyRollingFile.File = logs/log.log
log4j.appender.dailyRollingFile.Append = true
log4j.appender.dailyRollingFile.Threshold = DEBUG
log4j.appender.dailyRollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyRollingFile.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
?
### 配置输出到文件,且大小到达指定尺寸的时候产生一个新的文件 ###
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender 
log4j.appender.ROLLING_FILE.Threshold=ERROR 
log4j.appender.ROLLING_FILE.File=rolling.log 
log4j.appender.ROLLING_FILE.Append=true 
log4j.appender.ROLLING_FILE.MaxFileSize=10KB 
log4j.appender.ROLLING_FILE.MaxBackupIndex=
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout 
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
?
### 配置输出到邮件 ###
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From=chenyl@yeqiangwei.com
log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.To=chenyl@yeqiangwei.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
?
### 配置输出到数据库 ###
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (‘[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n‘)
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH‘.log4j‘
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
语法: SELECT * from limit startIndex,pageSize;
?
例:  SELECT * from limit 0,2;
每页显示两个,从第零个查;
SELECT * from limit 3;   # [0,n]
//分页
List<UsergetUserByLimit (Map<String,Integer> map);
<!--   分页-->
   <select id="getUserByLimit" parameterType="map" resultType="user">
      select * from mybatis.user limit #{startIndex},#{pageSize}
   </select>
?
@Test
   public void getUserByLimit(){
       SqlSession sqlSession = MybatisUtils.getSqlSession();
?
       UserMapper mapper = sqlSession.getMapper(UserMapper.class);
?
       HashMap<String,Integer> map new HashMap<String, Integer>();
       map.put("startIndex",0);
       map.put("pageSize",2);
?
      List<User> userList mapper.getUserByLimit(map);
      
      for (User user : userList){
          System.out.println(user);
      }
?
       sqlSession.close();
?
?
   //使用RowBounds分页
   List<UsergetUserByRowBounds ();
<!-- RowBounds分页-->
   <select id="getUserByLimit" parameterType="map" resultType="user">
      select * from mybatis.user
   </select>
@Test
   public void getUserByRowBounds(){
?
       SqlSession sqlSession = MybatisUtils.getSqlSession();
?
       //RowBounds实现
       RowBounds rowBounds new RowBounds(1, 2);
?
       //通过java代码层面实现分页
       List<User> userList = sqlSession.selectList("com.yuan.dao.UserMapper.getUserByRowBounds",null,rowBounds);
?
       for (User user : userList){
           System.out.println(user);
      }
?
  }
?
}
//绑定接口
<mappers>
<mapper class="com.yuan.dao.userMapper"/>
</mappers>
public static SqlSession getSqlSession(){
 return sqlSessionFactory.openSession(true);
}
 @Select("select * from user where id = #{id}")
   List<UsergetUsers();
?
   //方法存在多个参数,所有的参数前面必须加上@Param()注解
   @Select("select * from user where id = #{id}")
   User getUserById(@Param("id") int id);
?
?
   @Insert("insert into user(id,name,pwd) values (#{id},#{name},#{password})")
   int addUser(User user);
?
   @Update("update user set name=#{name),pwd=#{password} where id = #{id}")
   int updateUser(User user);
?
   @Delete("delete from user where id = #{id}")
   int seleteUser(@Param("id")int id);
Project Lombok makes java a spicier language by adding ‘handlers‘ that know how to build and compile simple, boilerplate-free, not-quite-java code.
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <version>1.18.10</version>
   <scope>provided</scope>
</dependency>
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
?
if
choose (when, otherwise)
trim (where, set)
foreach
Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存.
<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
<dependency>
   <groupId>org.ehcache</groupId>
   <artifactId>ehcache</artifactId>
   <version>3.8.1</version>
</dependency>
?
  • diskStore : ehcache支持内存和磁盘两种存储

    • path :指定磁盘存储的位置

  • defaultCache : 默认的缓存

    • maxEntriesLocalHeap=”10000”

    • eternal=”false”

    • timeToIdleSeconds=”120”

    • timeToLiveSeconds=”120”

    • maxEntriesLocalDisk=”10000000”

    • diskExpiryThreadIntervalSeconds=”120”

    • memoryStoreEvictionPolicy=”LRU”

  • cache :自定的缓存,当自定的配置不满足实际情况时可以通过自定义(可以包含多个cache节点)

    • name : 缓存的名称,可以通过指定名称获取指定的某个Cache对象

    • maxElementsInMemory :内存中允许存储的最大的元素个数,0代表无限个

    • clearOnFlush:内存数量最大时是否清除。

    • eternal :设置缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。根据存储数据的不同,例如一些静态不变的数据如省市区等可以设置为永不过时

    • timeToIdleSeconds : 设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。

    • timeToLiveSeconds :缓存数据的生存时间(TTL),也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。

    • overflowToDisk :内存不足时,是否启用磁盘缓存。

    • maxEntriesLocalDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。

    • maxElementsOnDisk:硬盘最大缓存个数。

    • diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。

    • diskPersistent:是否在VM重启时存储硬盘的缓存数据。默认值是false。

    • diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。

    • maxEntriesLocalHeap:是用来限制当前缓存在堆内存上所能保存的最大元素数量的。Ehcache规定如果在CacheManager上没有指定maxBytesLocalHeap时必须在各个Cache上指定maxBytesLocalHeap或者maxEntriesLocalHeap,但maxEntriesLocalHeap和maxBytesLocalHeap不能同时出现。也就是说我们不能在一个Cache上同时指定maxBytesLocalHeap和maxEntriesLocalHeap,当然我们也不能在Cache上指定maxEntriesLocalHeap的同时在CacheManager上指定maxBytesLocalHeap。但同时在CacheManager和Cache上指定maxBytesLocalHeap则是允许的。

要在程序中使用ehcache,首先要导包

 

13.6、自定义缓存-ehcache

技术图片

13.5、缓存原理

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存

  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存

  • 工作机制

    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中

    • 如果当前会话关闭了,这个回话对应的一级缓存就没了,但是我们想要的是,会话关闭了,一级缓存中的数据保存到二级缓存中

    • 新的回话查询信息,就可以从二级缓存中获取内容

    • 不同的mapper查出的数据会放在自己对应的缓存(map)中

13.4、二级缓存

  • 一级缓存也叫本地缓存

    • 与数据库同一次回话期间查询到的数据会放在本地缓存中;

    • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库

13.3、一级缓存

读写分离,主从复制

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

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

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

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

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

13.2、Mybatis缓存

 

  1. 什么是缓存[Cache]?

    • 存在内存中的临时数据

    • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

  2. 为什么使用缓存?

    • 减少和数据库的交互次数,减少系统开销,提高系统效率

  3. 什么样的数据能使用缓存

    • 经常查询且不经常改变的数据

13.1、简介

13、缓存

 

https://mybatis.org/mybatis-3/zh/dynamic-sql.html

具体内容看官方文档吧!!

 

  1. 导包

  2. 编写配置文件

  3. 编写实体类

  4. 编写实体类对应的Mapper接口和Mapper.xml文件

创建一个基础工程:

什么是动态sql:动态sql就是指根据不同的条件生成不同的sql语句;

12、动态SQL

 

https://www.jianshu.com/p/4ff554003c6e

11、一对多处理

  • 多个学生,对应一个老师

  • 对于学生这边而言,关联 多个多生关联一个老师【多对一】

  • 对于老师而言,集合 一个老师有很多学生【一对多】

技术图片

多对一:

10、多对一处理

 

参考博客:https://www.cnblogs.com/heyonggang/p/8638374.html

  1. 不支持多种参数构造器的重载

  2. 虽然省去了手动创建getter/setter方法的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度

缺点:

  1. 能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率

  2. 让代码变得简洁,不用过多的去关注相应的方法

  3. 属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等

优点:

优缺点:

 

Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

  1. 在实体类上加注解即可

  1. 导入依赖(或者下载jar)

https://www.2cto.com/kf/201709/682062.html

  1. 安装Lombok插件

使用步骤:

官方介绍:

9、Lombok

${}底层采用字符串拼接的方式绑定数据 字符串拼接方式: 优点:不但能绑定数据,还可以拼接表名,列名,关键字,运算符 缺点:可能会被SQL注入攻击 #{}底层采用?占位符的方式绑定数据 占位符的方式: 优点:可以防止SQL注入攻击 缺点:只能绑定数据,不能拼接表明,列名,关键字,运算符

#{}和#{}区别:

  • 基本类型的参数或者String类型,需要加上

  • 引用类型不需要加

  • 如果只有一个基本类型的话,可以忽略,但是建议大家都加上!

  • 我们在SQL中引用的就是我们这里的@Param()中设定的属性名!

关于@Param()注解

【注意】我们必须要将接口注册绑定到我们的核心配置文件中!

编写接口,增加注解

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

8.3、CRUD

技术图片

Mybatis详细执行流程:

底层:动态代理!

本质:反射机制实现!

  1. 测试

  1. 需要在核心配置文件中绑定接口

技术图片

  1. 注解在接口上实现

8.2、使用注解开发

  • 面向对象是指:我们考虑问题时,以对象为单位,考虑它的属性与方法;

  • 面向过程是指:我们考虑问题时,以一个具体流程(事务过程)为单位,考虑它的实现;

  • 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题,更多的体现就是对系统整体的架构;

三个面向的区别:

 

  • 接口从更深层次的理解,应是定义(规范、约束)与实现(名实分离的原则)的分离;

  • 接口的本身反映了系统设计人员对系统的抽象理解;

  • 接口应有两类:

    • 第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);

    • 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface);

    • 一个个体可能被有多个抽象面。抽象体与抽象面是有区别的。

关于接口的理解:

 

  • 大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程

  • 根本原因:解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好;

  • 在一个面向对象的系统中,系统的各种功能是由许许多多不同对象协作完成的。在这种病情况下,各个对象内部是如何实现自己的,对系统设计人员来说的不那么重要了;

  • 而各个对象之间的协作关系则成为系统设计的关键,小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要内容。面向接口编程就是按照这种思想来编程;

8.1、面向接口编程

8、使用注解开发

技术图片

7.3、分页插件

  1. 测试

 

  1. mapper.mxl

 

  1. 接口

不再使用sql实现分页

7.2、RowBounds分页(不建议在开发中使用)

  1. 测试

  1. Mapper.xml

  1. 接口

使用Mybatis实现分页,核心sql

 

7.1、使用Limit分页

 

  • 减少数据的处理量

思考:为什么要分页?

7、分页

  1. log4j的使用!直接运行刚才的查询!

  1. 配置log4j为日志的实现

  1. Log4j.properties 例:

  1. 先导入LOG4J的包;

  • Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;

  • 我们也可以控制每一条日志的输出格式;

  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

  • 最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

什么是LOG4J?

6.2、LOG4J

注意:一定要准确写出name和value的值,最好复制,防止出错。

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

STDOUT_LOGGING :标准日志输出!

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

 

  • SLF4J

  • LOG4J 【掌握】

  • LOG4J2

  • JDK_LOGGING

  • COMMONS_LOGGING

  • STDOUT_LOGGING 【掌握】

  • NO_LOGGING

技术图片

现在:日志工厂!

曾经:sout、debug

如果一个数据库操作出现了异常,我们需要排错,日志就是好的助手。

6.1、日志工厂

6、日志

  • resultMap 元素是 MyBatis 中最重要最强大的元素。

  • ResultMap 的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。

  • ResultMap 最优秀的地方在于,虽然你已经对它相当了解了,但是根本就不需要显式地用到他们。

  • 如果世界总是这么简单就好了。

结果集映射:

5.1、resultMap

5、解决属性名和字段名不一致的问题(ResultMap)

这里的每一个Mapper,就代表一个具体的业务!

技术图片

  • 连接到连接池的一个请求!

  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。

  • 用完之后赶紧关闭,否则资源被占用

SqlSession

  • 相当于数据库连接池

  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。

  • SqlSessionFactory 的最佳作用域是应用作用域

  • 最简单的就是使用单例模式或者静态单例模式。

SqlSessionFactory:

  • 一旦创建了 SqlSessionFactory,就不再需要它了

  • 局部变量

SqlSessionFactoryBuilder:

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

技术图片

4.8、生命周期和作用域

  • 接口和它的Mapper配置文件必须同名!   

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

注意点:

技术图片

MapperRegister:注册绑定我们的Mapper文件;

4.7、映射器(mappers)

4.6、其他配置

技术图片

技术图片

 

技术图片

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

4.5、设置

别名映射的类型
_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

下面是一些为常见的 Java 类型内建的相应的类型别名。它们都是不区分大小写的,注意对基本类型名称重复采取的特殊命名风格。

 

比如 domain.blog.Author的别名为 author;若有注解,则别名为其注解值。见下面的例子:

第二种在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。

第一种可以DIY别名,第二种则不行。

如果实体类比较多,建议使用第二种~

在实体类比较少的时候,使用第一种方式

 

扫描实体类的包,它的默认别名就为这个类的类名,首字母小写!

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

 

当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。

  • 类型别名是为 Java 类型设置一个短的名字。

  • 它只和 XML 配置有关。存在的意义仅在于用来减少类完全限定名的冗余。

4.4、类型别名(typeAliases)

  • 可以直接引用外部文件!

  • 可以在其中增加一些属性配置!

  • 如果两个文件有同一个字段,有限使用外部配置文件的!

  1. 在核心配置文件中引入

  1. 编写一个配置文件

技术图片

注意xml中的标签顺序!!!

 

这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。【db.properties】

我们可以通过properties属性来实现引用配置文件!

4.3、属性(properties)

 

Mybatis默认的事务管理器就是JDBC,连接池:POOLED!

学会使用多套运行环境!

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

MyBatis 可以配置成适应多种环境

4.2、环境配置(environments)

  • Mybatis-config.xml

4.1、核心配置文件

4、配置解析

 

  1. Java代码执行的时候,传递通配符% %

  2. 在sql拼接中使用通配符!

3.8、模糊查询怎么写

多个参数用Map或者注解!

只有一个基本类型参数的情况下,可以直接在sql中取到!

对象传递参数,直接在sql中取对象的属性即可!【parameterType="Object"】

Map传递参数,直接在sql中取出key即可!【parameterType="map"】

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

3.7、万能Map

 

  • 标签不要匹配错

  • resource绑定mapper需要使用路径

  • 程序配置文件必须符合规范

  • NullPointerException,没有注册到资源

  • 输出的xml文件中存在中文乱码的问题

  • maven资源没有导出问题

3.6、分析错误

 

注意点:增删改需要提交事务!

 

 

3.5、Delete

 

3.4、Update

 

3.3、Insert

 

  1. 测试

 

  1. 编写对应的Mapper中的sql语句

 

  1. 编写接口

 

  • id:就是对应namespace中的方法名;

  • resultType:sql语句执行的返回值;

  • parameterType:参数类型;

选择、查询语句;

3.2、select

namespace中的包名要和Dao/Mapper接口包名一致!

3.1、namespace

3、CRUD

 

技术图片

架构截图:

  1. 配置文件没有注册

  2. 绑定接口错误

  3. 方法名不对

  4. 返回类型不对

  5. Maven导出资源问题

可能会遇到的问题:

 

  • Junit测试

 

解决方法:在pom.xml文件内:build中配置resources,来防止我们资源导出失败的问题

  1. 报错:java.lang.ExceptionInInitializerError

    Maven导出资源错误

解决方法:在mybatis-config.xml中注册

MapperRegistry未注册

注意点:1. 报错:org.apache.ibatis.binding.BindingException: Type interface *** is not known to the MapperRegistry.

2.4、测试

  • 接口实现类由原来的UserDaoImpl转变为一个Mapper配置文件

 

  • Dao接口

 

  • 实体类

2.3、编写代码

  1. 编写mybatis工具类 mybatisUtils下

  1. 编写Mybatis的核心配置文件 resources下

2.2、创建一个模块

以上是关于Mybatis的主要内容,如果未能解决你的问题,请参考以下文章

SSM-MyBatis-05:Mybatis中别名,sql片段和模糊查询加getMapper

mybatis动态sql片段与分页,排序,传参的使用

MyBatis动态SQL标签用法

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

mybatis动态sql之利用sql标签抽取可重用的sql片段

[mybatis]动态sql_sql_抽取可重用的sql片段