MyBatis基础原理

MyBatis持久层框架

数据持久化:将程序的数据在持久状态和瞬时状态转化的过程

官方文档: MyBatis中文网

内存:断电即失

第一个程序

TeacherMapper接口,有一个获取所有Teacher的方法待实现

public interface TeacherMapper {

  List<Teacher> getTeacherList();

}
  1. 导入依赖(操作数据库时,还需要导入一个mysql-connector-java的依赖)
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.7</version>
</dependency>

  1. mybatis.xml文件连接数据库

jdbc.properties

driver=com.mysql.cj.jdbc.Driver
username=root
password=root
url=jdbc:mysql:///mybatis?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC

官方配置文件模板

<?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>

  1. 原本的dao接口实现类daoImpl,现在变成一个和接口同名的mapper.xml文件

    TeacherMapper.xml,就是把这里面的configuration全部换成mapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
          PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
          "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace写入完全限定名,表明这是哪个Mapper接口的实现类-->
<mapper namespace="com.changGe.li.mapper.TeacherMapper">

    <!--查询方法,id要和接口中的方法名相同,
     resultType写上返回值类型-->
    <select id="getTeacherList" resultType="com.changGe.li.pojo.Teacher">
        select * from teacher;
    </select>

</mapper>

  1. mybatis-config.xml配置文件中注册TeacherMapper的实现类(TeacherMapper.xml)

mybatis-config.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="jdbc.properties"></properties>

    <!--给类型起别名,以后其它文件再引用时,就可以直接使用别名了-->
    <typeAliases>
        <typeAlias type="com.changGe.li.pojo.Teacher" alias="teacher"/>
    </typeAliases>

    <!-- 环境 -->
    <environments default="development">
        <environment id="development">
            <!-- 事务管理器类型为jdbc  默认手动提交事务-->
            <transactionManager type="JDBC"/>
            <!-- 连接池状态是POOLED(连接) -->
            <dataSource type="POOLED">
                <!--#{driver}从配置文件中读取driver的值-->
                <!-- $是Statement模式读取,#是PreparedStatement模式,但是值会变成字符串格式
                    多数情况下用#,但是遇到如分页的情况时:必须用$
                 -->
                <!--这里如果用#,最后的值会变成'#{username}'-->
                <property name="driver" value="${driver}"/>
                <property name="url" value="jdbc:mysql:///mybatis?useUnicode=true&amp;ampcharacterEncoding=utf8"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--必须注册mapper,不然报错,就是让MyBatis知道应该去哪里找mapper文件
			注意:文件用/号来分隔,类用.号来分隔
		-->
    <mappers>
        <mapper resource="com/changGe/li/mapper/StudentMapper.xml"/>
        <mapper resource="com/changGe/li/mapper/TeacherMapper.xml"/>
    </mappers>

</configuration>

xml中的&要加上amp;来表示

<property name="url" value="jdbc:mysql:///mybatis?useUnicode=true&amp;ampcharacterEncoding=utf8"/>

  1. Mybatis工具类,获取sqlSession(数据库操作)对象
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtil {

  private static SqlSessionFactory sqlSessionFactory;

  static {

    try {
      //读取配置文件
      InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-onfig.xml");

      //工厂构建类 构建 得到sql会话工厂
      sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

    } catch (IOException e) {
      e.printStackTrace();
    }

  }

  //用工厂类来获取执行sql操作的对象
  public static SqlSession getSqlSession(){
    //打开会话,也就是开启和数据库的连接
    return sqlSessionFactory.openSession();
  }

}

  1. 用SqlSession对象来获取实现类对象,然后执行方法
@Test
public void test(){
  //工具类获取SqlSession对象
  SqlSession sqlSession = MyBatisUtil.getSqlSession();

  //底层用反射机制,获取了接口TeacherMapper的类对象
  TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);

  //接口被实现类TeacherMapper.xml实现了,调用接口就是调用实现类的方法
  List<Teacher> teacherList = mapper.getTeacherList();

  id:1,姓名是:秦老师
  for (Teacher teacher : teacherList) {
    System.out.println("id:"+teacher.getId()+",姓名是:"+teacher.getName());
  }
  

  //一定要关闭会话,免得占用资源
  sqlSession.close();

}
  1. 早年间官方给我们提供了一些默认的方法,可以通过传入方法路径,来直接执行.不过没有第一种方法好理解
@Test
public void test(){
  
  SqlSession sqlSession = MyBatisUtil.getSqlSession();

  TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);


  //sql会话时,直接调用接口中的方法
  List<Teacher> teacherList = sqlSession.selectList("com.changGe.li.mapper.TeacherMapper.getTeacherList");

  //id:1,姓名是:秦老师
  for (Teacher teacher : teacherList) {
    System.out.println("id:"+teacher.getId()+",姓名是:"+teacher.getName());
  }

  sqlSession.close();
}


注意事项

如果找不到对象,可能因为maven是找不到mapper.xml,用下面的代码,让maven在构建项目时把文件构建进来

<build>

  <resources>
    <resource>
      <!--将src,main,java下的.properties和.xml文件,可以被maven发现-->
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.properties</include>
        <include>**/*.xml</include>
      </includes>
      <filtering>false</filtering>
    </resource>
  </resources>
</build>

好像说mapper.xml中的中文注释也会出问题,可能是要把文件格式改成UTF-8


官方名词概念

三大对象

在后面的生命周期和作用域会讲解

完全限定名

就是可以让mybatis直接打到资源的一个精确名字,如com.changGe.li.pojo.Teacher


CRUD

对象中的值可以直接拿来用

<!-- 从parameterType中拿到的参数,可以直接作用于语句中 -->
<select id="getTeacherByIdAndName" resultType="teacher" parameterType="map">
  select * from teacher where id=#{id} and name = #{name};
</select>
@Test
public void test(){
  SqlSession sqlSession = MyBatisUtil.getSqlSession();

  TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);

  HashMap<String, String> map = new HashMap<String, String>();

  map.put("id","1");
  map.put("name","秦老师");
  Teacher teacherByIdAndName = mapper.getTeacherByIdAndName(map);
  System.out.println(teacherByIdAndName);
  
  sqlSession.close();

}

增删改一定要提交事务sqlsession.commit();

<insert id="addTeacher" parameterType="teacher">
  insert into teacher values(#{id},#{name})
</insert>

@Test
public void test(){
  SqlSession sqlSession = MyBatisUtil.getSqlSession();

  TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);

  Teacher teacher = new Teacher(2,"李长歌");

  mapper.addTeacher(teacher);

  //不提交事务,不更新数据
  sqlSession.commit();
  
  sqlSession.close();

}

获取更新时记录的key(slelectKey)

https://blog.csdn.net/kongkongyanan/article/details/86096657

<insert id="insertStudent">
  <!--通过LAST_INSERT_ID() 获得刚插入的自动增长的id的值。
            order属性设置成BEFORE,表示在插入前就获取对应的键
        -->
  <selectKey keyProperty="id" order="AFTER">
    SELECT LAST_INSERT_ID() AS ID
  </selectKey>
  insert into student values(#{id},#{name},#{tid})

</insert>
Student student = new Student();
student.setName("张三");
student.setTid(1);

mapper.insertStudent(student);

System.out.println(student.getId());

模糊查询

select * from teacher where name like concat('%',#{name},'%');
Teacher teacher = mapper.getTeacherByName("长歌");

配置优化

xml规定了所有标签的顺序,必须完全符合规定

properties,settings,

typeAliases,typeHandlers,

objectFactory,objectWrapperFactory,

reflectorFactory,plugins,

environments,databaseIdProvider,

mappers

多环境配置

<environments default="test">
  <environment id="development">
    <!--environment必须配置事务管理器和dataSource
            mybatis默认事务管理器是jdbc,但是还有一个,只要记得不只一个就行了
            -->
    <transactionManager type="JDBC"/>
    <!-- 数据库连接池:用完不关,可以回收让别人再用
             连接池状态是pooled(连接),还有unPooled和jedi(现在不用了)-->
    <dataSource type="POOLED">
    </dataSource>
  </environment>

  <environment id="test">
    <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>

属性优化properties 替换需要动态配置的属性值

<properties resource="jdbc.properties">
  <property name="username" value="root"/>
</properties>

<dataSource type="pooled">
  <!--先读取properties里的,再去读取${username}对应的配置文件中的属性,然后后来的覆盖前面的-->
  <property name="username" value="${username}"/>
</dataSource>

类型别名: 降低冗余的全限定类名书写

<typeAliases>
  <typeAlias type="com.changGe.li.pojo.Teacher" alias="teacher"></typeAlias>

  <!--自动为包下所有类,创建首字母小写的别名-->
  <package name="com.changGe.li.pojo"/>
</typeAliases>

<select id="getTeacherByName" resultType="teacher">

注解设置别名

@Alias("teacher")
public class Teacher {}

但是需要在mybatis-config.xml中,配置在哪个包下扫描注解

<typeAliases>
  <package name="com.changGe.li.pojo"/>
</typeAliases>

系统默认别名

基本类型加_,包装类是对应的基本类型,集合首字母小写

int 别名是 _int,Integer = int, Map = map

<select id="getTeacherByName" resultType="teacher" parameterType="_int">

settings系统配置:改变 MyBatis 的运行时行为

可以设置如日志,缓存懒加载

slf4j依赖

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>2.0.0-alpha4</version>
</dependency>
<settings>
  <!--MyBatis默认的日志-->
  <setting name="logImpl" value="SLF4J"/>
  <!--缓存-->
  <setting name="cacheEnabled" value="true"/>
  <!--懒加载-->
  <setting name="lazyLoadingEnabled" value="true"/>
</settings>

MapperGesitry注册,映射器: 直接告诉 MyBatis 到哪里去找映射文件

当用实现类或包注册时,要求:实现类和配置文件与接口同名,且同包!

<mappers>
  <!--1.当映射文件与接口同名,且同包时,写上接口名,会自动找到对应的映射文件-->
  <!--2.或者写上原接口的完全限定名,mybatisX插件会自动根据方法结构来解析出sql语句-->
  <mapper class="com.changGe.li.mapper.TeacherMapper"/>
  <!--将包内的映射器接口实现全部注册为映射器-->
  <package name="com/changGe/li/mapper"/>
</mappers>

如果想分离,要在resource包下创建和接口相同结构的包.

因为mybatis的resource是通过classpath来找文件的


生命周期和作用域

错误的使用可能会出现严重的并发问题

  1. 程序开始,配置文件被sqlsessionfactoryBuilder构建,
  2. 得到sqlsessionfatory工厂模式,
  3. 由此创建sqlsession对象,
  4. 产生对应接口的SQLMapper对象,
  5. 执行数据库操作,最后结束.

从 XML 中构建 SqlSessionFactory

  1. SqlSessionFactoryBuilder 可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例
  2. 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。

从 SqlSessionFactory 中获取 SqlSession

  1. 我们可以从SqlSessionFactory中获得 SqlSession 的实例

  2. SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。

通过 SqlSession 实例来直接执行已映射的 SQL 语句

  1. sqlsession执行rselectOne()或者selectList()等方法,直接执行sql操作,最后结束

  2. 这种方式对使用旧版本 MyBatis 的用户来说,比较熟悉。

更简洁的方式
  1. 使用指定了语句的参数和返回值相匹配的接口(比如 BlogMapper.class)

  2. 现在代码更清晰,更加类型安全不用担心可能出错的字符串字面值,以及强制类型转换

BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);

作用域



结果集映射:解决数据库字段与对象属性不对应的问题

作用就是:把数据库中返回的字段的值,映射到对象的属性上

对象中有id和age两个属性

@Data
@AllArgsConstructor
@NoArgsConstructor
@Alias("teacher")
public class Teacher {

  private int id;
  private String ame;

}

配置结果集映射

<!--这里的id对应着select标签中的resultMap
        返回值类型是Teacher类型
    -->
<resultMap id="tea" type="teacher">
  <id column="id" property="id"/>
  <!--把数据库中返回的字段name中的值,映射到对象的ame属性上-->
  <result column="name" property="ame"/>
</resultMap>


<select id="getTeacherByName" resultMap="tea" parameterType="teacher">
  select * from teacher where id = #{id} and name = #{ame};
</select>

执行查询

Teacher teacher1 = new Teacher(2, "李长歌");
Teacher teacher = mapper.getTeacherByName(teacher1);

写resultMap时,resultType就可以不用写了


日志工厂

Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j
  • JDK logging
  1. MyBatis 内置日志工厂:会基于运行时检测信息,选择日志委托实现

  2. 它会(按上面罗列的顺序)使用第一个查找到的实现

  3. 如果你的环境中并不存在 Log4J,你却试图调用了相应的方法,MyBatis 就会忽略这一切换请求 .

  4. 没有找到这些实现时,将会禁用日志功能


STDOUT_LOGGING(标准输出记录)

xml声明

<settings>
  <!--可选的值有SLF4J、LOG4J、LOG4J2、JDK_LOGGING、
        COMMONS_LOGGING、STDOUT_LOGGING(标准输出记录)、NO_LOGGING-->
  <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

执行结果

//读者入口
Reader entry: <?xml version="1.0" encoding="UTF-8" ?>
//检查类 com.changGe.li.mapper.StudentMapper 是否符合条件 [可分配给对象]  
Checking to see if class com.changGe.li.mapper.StudentMapper matches criteria [is assignable to Object]
  
Checking to see if class com.changGe.li.mapper.TeacherMapper matches criteria [is assignable to Object]
  
//打开 JDBC 连接  
Opening JDBC Connection
//创建连接 1312381159  
Created connection 1312381159.
//在 JDBC 连接 [com.mysql.cj.jdbc.ConnectionImpl@4e3958e7] 上将 autocommit(自动提交) 设置为 false  
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4e3958e7]
//准备中  
==>  Preparing: select * from teacher where id = ? and name = ?;
//参数
==> Parameters: 2(Integer), 李长歌(String)
//列  
<==    Columns: id, name
//行  
<==        Row: 2, 李长歌
//总计  
<==      Total: 1
//返回结果  
Teacher(id=2, name=李长歌)
//在 JDBC 连接 [com.mysql.cj.jdbc.ConnectionImpl@4e3958e7] 上将自动提交重置为 true  
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4e3958e7]
//关闭 JDBC 连接 [com.mysql.cj.jdbc.ConnectionImpl@4e3958e7]  
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4e3958e7]
//将连接 1312381159 返回到池  
Returned connection 1312381159 to pool.

Log4j :java日志

log4j_百度百科 (baidu.com)

使用Log4j框架的作用通俗的解释:

  • 能够控制日志信息想往哪里打就往哪里打,比如:控制台、文件、邮箱、数据库等等。
  • 能够控制日志信息想怎么打就怎么打,比如:我想要打印时间、程序的名称、程序的方法名、程序的行号、线程的名称等等。
  • 能够控制日志信息想打什么打什么,不想打的就不打,日志信息是分级别的,有时候我只想看错误的信息或者警告的信息,有时候我想看到所有的信息我想调试程序等等。

依赖

<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.17</version>
</dependency>

log4j.properties

#将等级为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

#日志输出级别:输出DEBUG级别及以上的日志信息
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  
简单使用
public class MyBatisTest {

  //在当前类运行时,输出日志
  private static Logger logger = Logger.getLogger(MyBatisTest.class);


  @Test
  public void test(){

    //在debug时,输出当前为debug模式
    logger.debug("当前为debug模式");

    SqlSession sqlSession = MyBatisUtil.getSqlSession();

    //输出一条普通信息:打印sqlSession
    logger.info(sqlSession);

    TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);

    Teacher teacher1 = new Teacher(2, "李长歌");
    Teacher teacher = mapper.getTeacherByName(teacher1);

    System.out.println(teacher);

    sqlSession.close();

    try {}catch (Exception e){}
    finally {
      logger.error("报错了");
    }

  }

}

日志文件的存放地址

部分日志信息


分页

RowBounds

<select id="getStudent" resultType="student">
  select * from student;
</select>
@Test
public void test(){

  SqlSession sqlSession = MyBatisUtil.getSqlSession();

  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

  //分页,从3开始显示,显示4个
  RowBounds rowBounds = new RowBounds(2, 4);

  //方法路径,参数和分页
  List<Student> students = sqlSession.selectList("com.changGe.li.mapper.StudentMapper.getStudent", null, rowBounds);


  for (com.changGe.li.pojo.Student student : students) {
    System.out.println(student);
  }

  sqlSession.close();

}

MyBatis的分页插件:PageHelper: MyBatis 分页插件 PageHelper


注解开发

根本目的为了解耦

@Select("select * from student;")
List<Student> getStudent();
  1. 运行的本质是:sqlSession(User.class)获取User的类对象,
  2. 然后获取其中所有的数据,读取特定数据上的注解,
  3. 得到其中的value(就是我们写的sql语句),
  4. 自动帮我们配置环境,运行.

Mapper中有一个sqlSession,里面保存了所有的配置信息


增删改

TeacherMapper

@Insert("insert into teacher values(#{id},#{name});")
/**
   * 将传参id的值交给@Param中的id,然后赋值给sql语句中的#{id}
   *
   * @Param中的参数名必须与#{}一致,mybatis就是从这里取值的
   */
int insertTeacher(@Param("id")int id,@Param("name")String name);
//设置开启自动提交
return sqlSessionFactory.openSession(true);

注解里的需要的参数,会自动去方法传参中找.

比如传参是对象,就会去自动匹配对象的字段。

@Insert("insert into teacher values(#{id},#{name});")
/**
   * 注解里的需要的参数,会自动去方法传参中找.
   */
int insertTeacher(Teacher teacher);
mapper.insertTeacher(new Teacher(4,"太平公主"));

运行分析

MyBatis运行流程(源码):https://zhuanlan.zhihu.com/p/67738448

简略易读版本: MyBatis的执行流程详解 - 知乎 (zhihu.com)

  1. Resource类读取配置文件,创建SqlSessionFactroyBuilder对象

    //读取配置文件的流
    InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
    
    //sql会话工厂构建类 构建 得到sql会话工厂
    sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    
  2. 这个对象底层用,创建了一个XMLConfig对象.

    public SqlSessionFactory build(InputStream inputStream) {
      return build(inputStream, null, null);
    }
    
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
      try {
        //通过流读取properties文件,创建XMLConfigBUiler对象
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        
        //XMLConfig对象读取xml配置文件
        //解析文件中数据,返回SqlSessionFactory对象
        return build(parser.parse());
        
      } catch (Exception e) {} finally {
        
        ErrorContext.instance().reset();
        
      }
      
    }
    
  3. XMLConfigBUiler对象读取xml配置文件,创建Configuration对象,这个对象中包含了所有的基本配置信息

    sqlSession中包含了configuration,里面有所有的配置信息,如environment(环境)

public Configuration parse() {
  
  if (parsed) {
    
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  
  parsed = true;
  parseConfiguration(parser.evalNode("/configuration"));
  
  return configuration;
}
  1. SqlSessionFactroy工厂对象,构建SqlSession对象(openSession)时,底层创建Transactional事务管理器–监听事务.同时创建Execetor执行器

    sqlSession中包含executor和transaction对象

return sqlSessionFactory.openSession();

SqlSessionFactory的实现类:DefaultSqlSessionFactory

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  
  //新建事务管理器
  Transaction tx = null;
  
  try {
    
    //获取环境
    final Environment environment = configuration.getEnvironment();
    
    //从环境中获取:事务管理器工厂
    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    
    //事务管理器赋值:所有的环境数据,等级和是否自动提交
    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    
    //创建执行器,专门用来执行sql操作,和缓存等
    final Executor executor = configuration.newExecutor(tx, execType);
    
    //把事务管理器和执行器都返回
    return new DefaultSqlSession(configuration, executor, autoCommit);
    
  } catch (Exception e) {
    //关闭事务管理器
    closeTransaction(tx); // may have fetched a connection so lets call close()
    
    throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
  }
  
}

lombok

它是一个插件,还需要maven依赖(也可以直接引用依赖)

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.22</version>
</dependency>

@Data @AllArgsConstractor @NoArgsConstractor

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

有一种说法是lombok改变了java的源码,让java语言出现了"文明断层"的情况

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

helloses

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值