MyBatis学习
文章目录
- MyBatis学习
- 1、MyBatis 配置解析
- 1.1、核心配置文件
- 1.2、事务管理器(transactionManager)
- 1.3、数据源(DataSource)
- 1.4、属性(properties)
- 1.5、类型别名(typeAliases)
- 1.6、设置(setting)
- 1.7、映射器(Mapper)
- 1.8、生命周期和作用域
- 2、解决属性名和字段名不一致的问题(resultMap)
- 2.1、问题
- 2.2、resultMap(结果集映射)
- 2.2.1、简单结果集映射**
- 2.2.2、复杂结果集映射**
- 3、日志
- 3.1、日志工厂
- 3.2、LOG4j
- 4、分页
- 4.1、使用Limit分页语法:
- 4.2、分页插件PageHelper
- 5、使用注解开发
- 5.1、面向接口编程
- 5.2、使用注解开发
- 6、Lombok
- 6.1、Lombok介绍
- 6.2、Lombok的使用步骤
1、MyBatis 配置解析
1.1、核心配置文件
- mybatis-config.xml
- MyBatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息
- MyBatis默认的事务管理器就是JDBC,默认连接池就是POOlED
1.2、事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type=“[JDBC|MANAGED]”):
- JDBC – 这个配置直接使用了 JDBC 的提交和回滚功能,它依赖从数据源获得的连接来管理事务作用域。默认情况下,为了与某些驱动程序兼容,它在关闭连接时启用自动提交。然而,对于某些驱动程序来说,启用自动提交不仅是不必要的,而且是一个代价高昂的操作。
- MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。
1.3、数据源(DataSource)
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
1.4、属性(properties)
我们可以通过properties属性来实现引用配置文件
这些属性都是可外部配置动态替换的,既可以在典型的Java属性文件中配置,又可以通过properties元素的子元素来传递。【db.properties】
编写数据库配置文件db.properties(这个文件要放到上面):
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSl=true;useUnicode=true;characterEncoding=utf8;serverTimezone=UTC
username=root
password=123456
在配置文件中引入:
<!-- 引入外部配置文件-->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
- 可直接引入外部文件
- 可以在其中增加一些属性配置
- 如果两个文件有同一字段,优先使用外部配置文件的!
1.5、类型别名(typeAliases)
- 1、实体类起别名
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<!-- 可以给实体类起别名-->
<typeAliases>
<typeAlias type="com.yjr.pojo.User" alias="user"/>
</typeAliases>
<!--这里的返回值类型用别名,不然com.yjr.pojo.User太长了-->
<select id="getUserLikeValue" resultType="user" >
select * from user where name like "%"#{value}"%"
</select>
- 2、包起别名
也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bea,例如:
<!-- 可以给包起别名-->
<typeAliases>
<!-- <typeAlias type="com.yjr.pojo.User" alias="user"/>-->
<package name="com.yjr.pojo"/>
</typeAliases>
每一个在包 com.yjr.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名(大写也行)。 比如 com.yjr.pojo.User 的别名为 user(或User);若有注解,则别名为其注解值。见下面的例子:
@Alias("radan")
public class User {
private int id;
private String name;
private String pwd;
}
总结:实体类比较少的时候多采用第一种方式;当实体类比较多的时候,建议采用第二种方式。
1.6、设置(setting)
- cacheEnabled:全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。
- lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。
- mapUnderscoreToCamelCase:是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
- logImpl:指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J(3.5.9 起废弃) | LOG4J2
1.7、映射器(Mapper)
MapperRegistry:注册绑定我们的Mapper文件
方式一(使用resource的资源引用–这个用斜杠划分)----推荐使用:
这样即可以将xml文件放到resource目录下,也可以避免下面的这些问题。
<mappers>
<mapper resource="com/yjr/dao/UserMapper.xml"/>
</mappers>
方式二(使用Class文件绑定注册):
<mappers>
<mapper class="com.yjr.dao.UserMapper"/>
</mappers>
注意点:
- 接口和它的Mapper配置文件必须同名!
- 接口和它的Mapper配置文件必须在同一个包下!
方式三(使用扫描包进行注册绑定):
<mappers>
<package name="com.yjr.dao"/>
</mappers>
注意点:
- 接口和它的Mapper配置文件必须同名!
- 接口和它的Mapper配置文件必须在同一个包下!
1.8、生命周期和作用域
作用域、生命周期是至关重要的,因为错误的使用会导致非常严重的并发问题。
SQLSessionFactoryBuilder:
- 一旦创建了SQLSessionFactory,就不在需要它
- 一般放在局部变量
SQLSessionFactory:
- 简单想象为:数据库连接池
- SQLSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有理由丢弃它或重新创建另一个实例。
- 因此SQLSessionFactory的最佳作用域是应用作用域。
- 最简单的就是使用单例模式或者静态单例模式。
SQLSession:
- 连接到连接池的一个请求!
- SQLSession的实例不是线程安全的,因此不能被共享的,所以它的最佳作用域是请求或方法作用域。
- 用完之后需要赶紧关闭 ,否则资源被占用!
2、解决属性名和字段名不一致的问题(resultMap)
2.1、问题
数据库中的字段:
实体类中的字段:
public class User {
private int id;
private String name;
private String password; //显然不一致
}
结果:
问题:当实体类的字段名和数据库中字段名不一致时,程序可以执行,但是测试的结果是查询的所有记录的该字段值为null。
解决方法:
- 在sql字段中起别名
<select id="getAllUsers" resultType="User">
select id,name,pwd as password from user
</select>
2.2、resultMap(结果集映射)
- resultMap 元素是 MyBatis 中最重要最强大的元素。
- ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
2.2.1、简单结果集映射**
column:数据库中的字段 property:实体类中的属性
<!--结果集映射-->
<resultMap id="userMap" type="User">
<!--column:数据库中的字段 property:实体类中的属性 -->
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="password" column="pwd"/>
</resultMap>
<!-- 查询语句-->
<select id="getAllUsers" resultMap="userMap">
select * from user
</select>
2.2.2、复杂结果集映射**
3、日志
- SLF4J (掌握)
- LOG4J (掌握)
- LOG4J2
- JDK_LOGGING
- COMMONS_LOGGING
- STDOUT_LOGGING (掌握)
NO_LOGGING
3.1、日志工厂
在MyBatis中具体事宜哪一个日志,在设置中设定!
STDOUT_LOGGING标准日志输出
在mybatis核心配置文件中,配置日志。
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
STDOUT_LOGGING标准日志–打印结果
3.2、LOG4j
什么是log4j?
- Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件等。
- 可以控制每一条日志的输出格式;
- 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
- 可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
- 先导入LOG4j的相关依赖
<!--日志 start-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
<!--日志end-->
- 配置log.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/yjr.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
- 配置log4j为日志的实现
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
- log4j的使用
简单使用
- 在要使用Log4j的类中,导入包import org.apache.log4j.Logger;
- 日志对象,参数为当前的class
static Logger logger= Logger.getLogger(UserDaoTest.class);
- 日志级别
logger.info("info:进入了testLog4j方法");
logger.debug("debug:进入了testLog4j方法");
logger.error("error:进入了testLog4j方法");
4、分页
思考:为什么分页?–减少数据的处理量
4.1、使用Limit分页语法:
select * from user limit startIndex,pageSize #startIndex:其实下标(默认从0开始,pageSize :一页的大小)
select * from user limit 3; #[0,n]
使用MyBatis实现分页,核心SQL
- 接口
//分页
List<User> getUserByLimit(Map<String,Integer> map);
- Mapper.xml
<!--分页-->
<select id="getUserByLimit" parameterType="map" resultMap="userMap" >
select * from user limit #{startIndex},#{pageSize}
</select>
- 测试
@Test
public void getUserByLimit() throws IOException {
HashMap hashMap=new HashMap();
hashMap.put("startIndex",0);
hashMap.put("pageSize",2);
//1.获取SQLSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//方式一:getMapper-----目前最好用
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println(mapper.getUserByLimit(hashMap));
sqlSession.close();
}
4.2、分页插件PageHelper
参考资料:PageHelper中文文档
5、使用注解开发
5.1、面向接口编程
根本原因:解耦,可拓展,提高复用;在分层开发中,上层不管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好。
接口的理解:
- 接口从更深层次的理解,就是定义(规范,约束)与实现的分离
- 接口的本身反映了系统设计人员对系统的抽象理解。
- 接口应有两类:
- 第一类是对一个个体的抽象,它可对应为一个抽象体(Abstract Class);
- 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface);
- 一个体由可能有多个抽象面。抽象体与抽象面试有区别的。
三个面向区别: - 面向对象是指:我们考虑问题时,以对象为单位,考虑它的属性及方法。
- 面向过程是指,我们在考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现。
- 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题,更多体现的是对系统整体的架构。
5.2、使用注解开发
- 注解直接在接口上实现
//查询所有用户
@Select("select * from user")
List<User> getAllUsers();
- 需要在核心配置文件中绑定接口
<!-- 绑定接口-->
<mappers>
<mapper class="com.yjr.dao.UserMapper"/>
</mappers>
- 测试
@Test
public void getAllUsersTest() throws IOException {
//1.获取SQLSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//方式一:getMapper-----目前最好用
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println(mapper.getAllUsers());
sqlSession.close();
}
注意点(实体类和数据库中的字段出现不一致):
@Select("select * from user")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "name", column = "name"),
@Result(property = "password", column = "pwd")
//column :数据库中的名字 property:实体类中的名字
})
List<User> getAllUsers();
用@Results注解来解决上述问题。
MyBatis详细的执行流程
6、Lombok
6.1、Lombok介绍
Lombok项目是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能。不需要再写getter、setter或equals方法,只要有一个注解,就有一个功能齐全的构建器、自动记录变量等等。
常用注解:
@Data:无参构造、get、set、toString、hasCode、equals
@AllArgsConstructor:有参构造
@NoArgsConstructor:无参构造
@toString:生成一个toSring()方法
@Getter:给所有的属性生成get方法
@Setter:给所有的属性生成set方法
Lombok的优点:
- 能通过注解的1方法自动生成构造器、getter/setter、equals、hashcode、toString等方法,提升了开发效率
- 让代码变得简洁,不用过多的去关注相应的方法
- 属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等。
Lombok的缺点:
- 不支持多种参数构造器的重载
- 虽然省去了手动创建各种方法的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度。
6.2、Lombok的使用步骤
使用步骤:
- 在IDEA中按照Lombok插件!
- 在项目中导入lombok的包
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
- 在实体类上加注解
package com.yjr.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
@AllArgsConstructor
public class User {
private int id;
private String name;
private String password;
}