MyBatis基础原理
MyBatis持久层框架
数据持久化:将程序的数据在持久状态和瞬时状态转化的过程
官方文档: MyBatis中文网
内存:断电即失
第一个程序
TeacherMapper接口,有一个获取所有Teacher的方法待实现
public interface TeacherMapper {List<Teacher> getTeacherList();}
- 导入依赖(操作数据库时,还需要导入一个mysql-connector-java的依赖)
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version>
</dependency>
- 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 configurationPUBLIC "-//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>
原本的dao接口实现类daoImpl,现在变成一个和接口同名的mapper.xml文件
TeacherMapper.xml,就是把这里面的configuration全部换成mapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//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>
- mybatis-config.xml配置文件中注册TeacherMapper的实现类(TeacherMapper.xml)
mybatis-config.xml
注意:文件用/号来分隔,类用.号来分隔
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//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&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&ampcharacterEncoding=utf8"/>
- 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();}}
- 用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();}
- 早年间官方给我们提供了一些默认的方法,可以通过传入方法路径,来直接执行.不过没有第一种方法好理解
@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必须配置事务管理器和dataSourcemybatis默认事务管理器是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来找文件的
生命周期和作用域
错误的使用可能会出现严重的并发问题
- 程序开始,配置文件被sqlsessionfactoryBuilder构建,
- 得到sqlsessionfatory工厂模式,
- 由此创建sqlsession对象,
- 产生对应接口的SQLMapper对象,
- 执行数据库操作,最后结束.
从 XML 中构建 SqlSessionFactory
- SqlSessionFactoryBuilder 可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
- 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。
从 SqlSessionFactory 中获取 SqlSession
我们可以从SqlSessionFactory中获得 SqlSession 的实例。
SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
通过 SqlSession 实例来直接执行已映射的 SQL 语句
sqlsession执行rselectOne()或者selectList()等方法,直接执行sql操作,最后结束
这种方式对使用旧版本 MyBatis 的用户来说,比较熟悉。
更简洁的方式
使用指定了语句的参数和返回值相匹配的接口(比如 BlogMapper.class)
现在代码更清晰,更加类型安全,不用担心可能出错的字符串字面值,以及强制类型转换。
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
MyBatis 内置日志工厂:会基于运行时检测信息,选择日志委托实现。
它会(按上面罗列的顺序)使用第一个查找到的实现。
如果你的环境中并不存在 Log4J,你却试图调用了相应的方法,MyBatis 就会忽略这一切换请求 .
当没有找到这些实现时,将会禁用日志功能。
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);@Testpublic void test(){//在debug时,输出当前为debug模式logger.debug("当前为debug模式");SqlSession sqlSession = MyBatisUtil.getSqlSession();//输出一条普通信息:打印sqlSessionlogger.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();
- 运行的本质是:sqlSession(User.class)获取User的类对象,
- 然后获取其中所有的数据,读取特定数据上的注解,
- 得到其中的value(就是我们写的sql语句),
- 自动帮我们配置环境,运行.
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)
Resource类读取配置文件,创建SqlSessionFactroyBuilder对象
//读取配置文件的流 InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");//sql会话工厂构建类 构建 得到sql会话工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
这个对象底层用流,创建了一个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();}}
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;
}
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语言出现了"文明断层"的情况
MyBatis基础原理相关推荐
- 后端技术:mybatis插件原理详解
关注"Java后端技术全栈" 回复"面试"获取全套面试资料 上次发文说到了如何集成分页插件MyBatis插件原理分析,看完感觉自己better了,今天我们接着来 ...
- javaweb实训第六天下午——Mybatis基础
Mybatis基础 1.课程介绍 2.为什么需要Mybatis 3.初识Mybatis 3.1.Mybatis是什么 3.1.1.什么是框架 3.1.2.什么叫数据库持久化 3.1.3.什么是ORM ...
- MyBatis基础学习知识点2
本文衔接MyBatis基础学习知识点1,继续对以下两个问题进行探讨 1.dao配置文件主要是用来干什么的?如何进行配置? 2.使用测试方法测试程序运行是如何实现的?每条语句起什么作用? 目录 dao配 ...
- java mybatis基础
java mybatis基础 1.1 什么是mybatis? mybatis是一个优秀的持久层框架. 避免几乎所有的JDBC代码和手动设置参数以及获取结果集的过程. 可以使用简单的xml或者注解来配置 ...
- 面试官:你分析过mybatis工作原理吗?
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 Mybatis工作原理也是面试的一大考点,必须要对其非常清晰,这样 ...
- Mybatis底层原理学习(二):从源码角度分析一次查询操作过程
在阅读这篇文章之前,建议先阅读一下我之前写的两篇文章,对理解这篇文章很有帮助,特别是Mybatis新手: 写给mybatis小白的入门指南 mybatis底层原理学习(一):SqlSessionFac ...
- MyBatis基础入门《九》ResultMap自动匹配
MyBatis基础入门<九>ResultMap自动匹配 描述: Mybatis执行select查询后,使用ResultMap接收查询的数据结果. 实体类:TblClient.java 接口 ...
- Mybatis基础:增删改查、模糊查询、多条件查询
Mybatis基础:增删改查.模糊查询.多条件查询http://www.bieryun.com/3132.html 1.新建测试数据库,根据实体类属性创建 2.实体类 [java] view plai ...
- Mybatis运行原理及源码解析
Mybatis源码解析 一.前言 本文旨在mybatis源码解析,将整个mybatis运行原理讲解清楚,本文代码地址: https://github.com/lchpersonal/mybatis-l ...
最新文章
- leetcode解题文件夹
- MTK深圳公司嵌入式软件工程师笔试题(含部分答案)
- mysql锁等待问题
- ARM汇编伪指令 .word
- 混沌数学之Rössler(若斯叻)吸引子
- E-Learning是学习系统而不是教育系统
- 利用sobel算子提取图像的水平特征和竖直特征
- Add library ‘Maven: ..to classpath
- 响应式设计就是这个时代最值得学习、时间的趋势
- 英特尔主板快捷启动键_电脑小匠电脑硬件知识科普——主板接口篇
- Linux多线程编程之pthread
- 【音视频】使用DXGI实现多屏幕采集(4-2)
- C#做一年小孩做一个口算题生成器
- 止增笑耳的星际迷航前传
- UE4 Pak包热更新
- 【转载】Aquanaut:水下变形金刚
- tableau:柱图的两种实现方式
- tensorflow 1.10下Mask RCNN实现自己数据集
- 解决Type interface com.kuang.mapper.UserMapper is not known to the MapperRegistry.的问题
- MWCS2019:中国联通与TCL通讯5G终端创新联合研发中心正式揭牌
热门文章
- attend,join,participate,take part in
- 包含高知漫画家珍贵作品的艺术项目“NAKED Manga Mappin’!”3月6日(周五)起在高知龙马机场展出
- 神经网络理论及应用答案,神经网络理论名词解释
- R语言笔记——”org.Hs.eg.db“脱坑记录
- 微信——产品设计分析报告
- videojs实现视频打点标记 Vue
- 高价值行为用户一键同步,精准投放提升广告效率
- godaddy新建二级域名
- direction: rtl;
- 汇编指令学习(ADD,SUB,MUL,DIV,XADD,INC,DEC,NEG)