MyBatis文档网址:https://mybatis.org/mybatis-3/zh/index.html
- Mybatis笔记
- 1. 创建第一个Mybatis程序
- 1.1 搭建环境
- 1.2 创建模块
- 1.3 写代码
- 2. 增删改查CRUD
- 2.1 namespace
- 2.2 根据ID查用户
- 2.3 插入用户信息(增删改需要提交事务)
- 2.4 关于事务的提交的两种方式
- 2.5 删、改(需要提交事务)
- 3. 使用Map去完成参数传递
- 小总结:
- 4. 配置
- 4.1 核心配置文件
- 4.2 环境配置
- 4.3 属性(properties)
- 4.4 类型别名(typeAliases)
- 4.5 映射器(mappers)
- 5. 生命周期
- 6. 结果映射
- 7.日志
- 7.1 标准的日志工程实现:
- 7.2 log4j
- 8. 分页
- 8.1 mybatis分页的实现(传统的方式 limit)
- 9. 使用注解开发
- 9.1 注解开发
- 9.2 注解增删改查
- 10.Lombok
- 11. 多对一的处理
- 11.1 方式一:
- 11.2 方式二:(按结果嵌套处理)(容易一点)
- 12. 一对多的处理
- 12.1 方式一:(嵌套查询)
- 12.2 方式二:(按结果嵌套处理)(容易一点)
- 13. 动态SQL(重要)
- 13.1 if
- 13.2 choose、when、otherwise
- 13.3 trim、where、set
- 13.4 foreach
- 13.5 script
- 13.6 标签(SQL片段)
- 14. 缓存
- 14.1 一级缓存
- 14.2 二级缓存
- 14.3 缓存原理
1.加入maven依赖
mysql mysql-connector-java5.1.47 org.mybatis mybatis3.5.2
2.在resources目录下,新建mybatis-config.xml,
3.并将官方文档的内容粘贴进去。
注意: 这里的resource是用斜杠分隔的,并且要指向自己写的mapper.xml文件。
1.创建utils类
2.分别获取SqlSessionFactory和SqlSession对象。
// SqlSessionFactory -->sqlSession public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { // 使用Mybatis第一步: // 获取sqlSessionFactory对象 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } // 使用Mybatis第二步: // 从 SqlSessionFactory 中获取 SqlSession // 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。 // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。 // 你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }1.3 写代码
1.编写实体类(各个字段与表对应起来)(为了防止出现问题,尽量将实体类序列化)
实现Serializable接口。
package com.hui.pojo; // 实体类 public class User implements Serializable { 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;} }
2.编写dao接口,也可以取名mapper
public interface UserMapper { ListgetUserList(); }
3.写接口对应的mapper.xml文件
4.在pom文件中改一下资源路径 (重要)
src/main/java ***.xml false src/main/resources ***.xml false
5.编写测试类,全类名尽量与src一致(类名除外)
public class UserMapperTest { @Test public void test(){ // 第一步:获取SqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); // 方式一:getMapper UserMapper mapper = sqlSession.getMapper(UserMapper.class); ListuserList = mapper.getUserList(); for (User user : userList) { System.out.println(user); } // 关闭SqlSession sqlSession.close(); } }
即可查询成功。
2. 增删改查CRUD 2.1 namespace配置文件中namespace中的名称为对应Mapper接口或者Dao接口的完整包名,必须一致!(用点.分隔包名)
1.先在接口里面定义方法
2.在mapper.xml文件里面写查询语句,指定参数类型和返回值类型,传入的变量直接用 #{接口中参数变量} 即可
1.接口参数为User
2.在写配置文件的时候,指定参数类型是User,使用变量的时候可以直接使用User的属性。如下图:
3.测试代码(增删改需要提交事务)
方式一:在编写代码的时候,写
sqlSession.commit();
方式二:在工具类中使用openSession的重载方法,参数为true即可。(参数的意思是autoCommit)
与以上增加类似。
delete
update
1.接口中参数声明为Map形式
2.参数类型是小写的map, 里面值的类型可以是map的键
3.测试代码
Map传递参数,直接在sql中取出key即可!【parameterType=“map”】
对象传递参数,直接在sql中取对象的属性即可! 【parameterType=“Object”】
只有一个基本类型参数 的情况下,可以直接在sql中取到!
多个参数:用Map,或者注解@Param("") 在下面9.2中有讲到!
一般命名为:mybatis-config.xml
configuration(配置) properties(属性) settings(设置) typeAliases(类型别名) typeHandlers(类型处理器) objectFactory(对象工厂) plugins(插件) environments(环境配置) environment(环境变量) transactionManager(事务管理器) dataSource(数据源) databaseIdProvider(数据库厂商标识) mappers(映射器)4.2 环境配置
MyBatis 可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
学会使用配置多套运行环境。
可以引入外部的配置
1.新建db.properties文件,里面写上一些配置。
如果里面和外面的配置冲突了,优先使用外面的配置。
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
第一种写法:
...
第二种写法:(扫描一个包)
第三种写法:(注解方式)
直接在类的上面使用注解@Alias(“name”)
@Alias("author") public class Author { ... }
其他别名的映射:
指定mapper位置
方式一:使用相对于类路径的资源引用:
...
方式二:使用映射器接口实现类的完全限定类名:
...
对于方式二的注意点:
· 接口和他的Mapper配置文件必须同名!
· 接口和t
生命周期:
SqlSessionFactoryBuilder:
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。
SqlSessionFactory:
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
SqlSession:
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
几种关系:
当表的字段名与实体类字段名不对应的时候,要进行映射。(在mapper.xml文件中)
实体类对应属性名property,数据库字段名column.
然后就可以使用了
7.日志 7.1 标准的日志工程实现:7.2 log4j
什么是Log4j?
·Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件
·我们也可以控制每一条日志的输出格式;
·通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。·通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
1.先导入log4j依赖
log4j log4j1.2.17
2.增加文件log4j.properties(可以写成其他的)
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
3.配置log4j为日志实现
4.简单使用
a.在需要使用Log4j的类中,导入包 import org.apache.log4j.Logger;
b.日志对象,参数为当前类的class
static Logger logger = Logger.getLogger(UserMapperTest.class);
c.举例
public class UserMapperTest { static Logger logger = Logger.getLogger(UserMapperTest.class); @Test public void log4jTest(){ logger.info("info:进入了testLog4j"); logger.debug("debug:进入了testLog4j"); logger.error("error:进入了testLog4j"); } }8. 分页 8.1 mybatis分页的实现(传统的方式 limit)
首先mysql的分页,limit的用法
a.对于一个参数的情况就是显示出前n行数据
select * from product limit 3; // 显示前三行
b.limit有两个参数,第一个参数表示从第几行数据开始查,第二个参数表示查几条数据.
select * from product limit 3,2; //“limit 3,2”表示从第四行数据开始,取两条数据。
1.定义接口
2.xml文件实现
3.测试
1.注解形式:(在接口文件里面直接添加注解)
public interface UserMapper { @Select("select * from user") ListgetUsers(); }
2.在mybatis-config.xml文件中添加类路径映射,绑定接口。
本质上是利用Java反射,底层代理。
注意: 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的 *** 作,最好用 XML 来映射语句。
有关#{} 和 ${}:
#{}是预编译的,可以有效防止sql注入。
有关@Param注解:
1.如果是一个参数,可以忽略注解,但是建议写上。
2.但是如果是多个参数,必须要使用 @Param 注解(基本类型和String得加,引用类型就不用加了)
3.@Param("")注解的意思是,上面的sql语句中用到的变量是从这个注解里取到的。(重要)
一些增删改查示例:
除了日志功能,还有给实体类使用的@Data注解,省去写get、set方法。
如果实体类写完不想写get,set等等方法,只需要在实体类前加一个@Data注解,方法如下:
1.先确保有Lombok插件
2.pom文件中添加依赖
org.projectlombok lombok
3.实体类前加注解@Data
可以查看:
注意:
@Data除了get、set方法外,还提供了equals、canEqual、hasCode、toString方法,以及无参的构造方法。
可以使用 @AllArgsConstructor 注解添加有参的构造方法,但此时无参的会消失。
可以在添加 @NoArgsConstructor 注解添加无参的构造方法。
现有Student表和Teacher表,他们是多对一的关系。
实体类:
@Data public class Teacher{ private int tid; private String tname; } @Data public class Student{ private int sid; private String sname; private Teacher teacher; }11.1 方式一:
联合查询如下(子查询):
注意:在下面的子查询中,写的是id=#{id},而上面却是tid。
这是因为上面resultMap中对象的那个column只有一个参数,所以肯定会匹配到那个tid,也就是说id=#{id}这里大括号里的变量名取什么都行。
查询结果:
实体类:
@Data public class Student{ private int sid; private String sname; private int tid; } @Data public class Teacher{ private int tid; private String tname; private List12.1 方式一:(嵌套查询) 12.2 方式二:(按结果嵌套处理)(容易一点)students; }
小结:
1.关联- association【多对一】
2.集合- collection 【一对多】
3. javaType & ofType
1. JavaType 用来指定实体类中属性的类型.
2. ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型!
什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句。
if
choose (when, otherwise)
trim (where, set)
foreach
使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。比如:
13.2 choose、when、otherwiseSELECT * FROM user WHERe 1=1 AND title like #{title}
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
若两者都没有传入,就返回标记为 featured 的 User。
where 元素:
where元素只会在子元素返回任何内容的情况下才插入 “WHERe” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
trim元素:
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
... ...
提示: prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。
set元素:
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。
13.4 foreachupdate Author where id=#{id} username=#{username}, password=#{password}, email=#{email}, bio=#{bio}
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
提示: 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
13.5 script要在带注解的映射器接口类中使用动态 SQL,可以使用 script 元素。
@Update({""}) void updateAuthorValues(Author author);13.6
使用
提示: 最好基于单表来定义SQL片段。
Mybatis 使用到了两种缓存:本地缓存(local cache)(一级缓存)和二级缓存(second level cache)。
14.1 一级缓存一级缓存是默认开启的,关不掉。
只在一次sqlSession中有效,也就是拿到连接到关闭连接的这个区间段!
每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询结果都会被保存在本地缓存中,所以,当再次执行参数相同的相同查询时,就不需要实际查询数据库了。本地缓存将会在做出修改、事务提交或回滚,以及关闭 session 时清空。
默认情况下,本地缓存数据的生命周期等同于整个 session 的周期。由于缓存会被用来解决循环引用问题和加快重复嵌套查询的速度,所以无法将其完全禁用。但是你可以通过设置 localCacheScope=STATEMENT 来只在语句执行时使用缓存。
注意,如果 localCacheScope 被设置为 SESSION,对于某个对象,MyBatis 将返回在本地缓存中唯一对象的引用。对返回的对象(例如 list)做出的任何修改将会影响本地缓存的内容,进而将会影响到在本次 session 中从缓存返回的值。因此,不要对 MyBatis 所返回的对象作出更改,以防后患。
你可以随时调用以下方法来清空本地缓存:
void clearCache()
确保 SqlSession 被关闭:
void close()14.2 二级缓存
· 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
· 基于namespace级别的缓存,一个名称空间,对应一个二级缓存
· 工作机制
· 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
· 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话提交或关闭的时候,一级缓存中的数据被保存到二级缓存中;
· 新的会话查询信息,就可以从二级缓存中获取内容;
· 不同的mapper查出的数据会放在自己对应的缓存(map)中;(也就是说只要开启了二级缓存,在同一个Mapper下就有效)
开启步骤:
1.开启全局缓存(mybatis-config.xml中setting里)
2.在SQL映射文件(xxxmapper.xml)中添加一行:
也可以指定的详细一些:
14.3 缓存原理
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)