Mybatis复习1——B站

1 简介

参考文档:https://mybatis.org/mybatis-3/zh/index.html
优秀持久化框架,使用简单的xml来映射pojo到数据库
简化JDBC代码

Mybatis与Hibernate区别:
Mybatis:半自动映射框架,需要开发人员提供:POJO、SQL、映射关系,可以配置动态SQL并优化,支持存储过程。适合复杂的需要优化性能的项目。
Hibernate:全自动映射框架,需要开发人员提供:POJO、映射关系,自动生成SQL,无法优化,不支持存储过程,多表查询差。适合场景不复杂对性能要求不高。

工作原理

  1. 读取mybatis-config.xml配置
  2. 加载Mapper.xml映射文件
  3. 构造会话工厂
  4. 创建会话对象
  5. 执行器执行
  6. 连接输入和数据库映射语句对象并输出

持久化

将数据转化成持久状态,即存入数据库或者放在硬盘的文件里

持久层:Dao层、Service层、Controller层

2 搭建环境

2.1 创建数据库

-- 新建数据库
create database `ooo`;
use `ooo`;

-- 新建表
CREATE TABLE `user` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(11) DEFAULT NULL,
  `age` INT(3) DEFAULT NULL,
  `salary` INT(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8

-- 插入数据
INSERT INTO `user` VALUES
(NULL,'pp1',1,567),
(NULL,'pp2',2,1246),
(NULL,'pp3',35,54),
(NULL,'pp4',15,533467),
(NULL,'pp5',17,2355),
(NULL,'pp6',82,23),
(NULL,'xiaopi3',21,NULL)

2.2 创建idea项目

创建一个空的maven项目

如果需要再在工程里建立子工程,则删除src目录,新建模块即可,父工程的pom依赖在子工程中可以使用

使用mybatis需要引用依赖:

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>

由于需要连接数据库和单元测试,再添加以下两个依赖:

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.1</version>
    <scope>test</scope>
</dependency>

2.3 编写核心配置文件

在resources目录下,新建mybatis核心配置文件: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>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ooo?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments></configuration>

注意:在xml中无法写&,必须转义:&amp;
对于mysql8的还需要加上serverTimezone=UTC8

2.4 编写mybatis工具类

该工具类主要实现功能为获取sqlSession,该实例用来操作sql的,工具类建议直接全静态

public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

2.5 编写POJO

这里使用lombok自动生成get和set等方法,lombok依赖为:

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.16</version>
    <scope>provided</scope>
</dependency>

pojo类为:

@Data
public class User {
    private int id;
    private String name;
    private int age;
    private int salary;
}

2.6 编写dao接口

UserMapper.java

public interface UserMapper {
    List<User> findAll();
}

2.7 编写dao接口配置文件

类似Impl文件,UserMapper.xml

<?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">
<mapper namespace="com.xiaopi3.dao.UserMapper">
    <select id="findAll" resultType="com.xiaopi3.pojo.User">
        select * from user;
    </select>
</mapper>

注意:xml中的类型,应该写全路径类
namespace:相当于需要Impl的接口是哪个类
id:相当于Impl的哪个方法
resultType:如果结果一条数据是一个类型,则使用该属性

2.8 单元测试

@Test
public void test(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> all = userMapper.findAll();
    for (User user : all) {
        System.out.println(user);
    }
    sqlSession.close();
}

2.9 排错

  1. 调用的mapper未注册
    该问题出现的原因是没有将mapper.xml注册到mybatis核心配置文件中去,解决如下,在核心配置中的configuration标签内加上该标签:(resource必须使用/作为分割符)
<mappers>
    <mapper resource="com/xiaopi3/dao/UserMapper.xml"></mapper>
</mappers>

当mapper配置文件很多时,也可以使用通配符:

<mappers>
    <mapper resource="com/xiaopi3/dao/*Mapper.xml"></mapper>
</mappers>
  1. 出现找不到mapper.xml文件
    该问题是由于maven默认不会导出除java外的其他格式文件,需要在pom中增加以下配置:
<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>

再次运行,即可!

2.10 优化

每个线程都应该有它自己的 SqlSession 实例。

SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求方法作用域绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行

绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。

换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:

try (SqlSession session = sqlSessionFactory.openSession()) {
  UserMapper mapper = session.getMapper(UserMapper.class);
  // 你的应用逻辑代码
}

或者使用传统的try catch finally,放在finally中

3 CRUD

注意:增删改必须要注意到事务的提交方式,openSession()如果不传参数,默认false,不自动提交事务,需要手动commit

增删改操作类似,不多赘述

3.1 select

查询语句中有几个重要属性:
id:对应namespace中的类的某个方法名,一个方法对应一个sql语句
resultType:对应sql语句的返回值类型,即方法的返回值类型(返回值类型指的是每一条数据的类型)
parameterType:参数类型,如int

传参方式:使用#{参数名},使用#{}这种方式,相当于去取java类中的变量,使用${}相当于取配置文件中的变量
在这里插入图片描述

接口

User getById(int id);

配置

<select id="getById" parameterType="int" resultType="com.xiaopi3.pojo.User">
    select * from user where id=#{id}
</select>

调用

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getById(2);

3.2 insert

接口:

int addUser(User user);

配置:

<insert id="addUser" parameterType="com.xiaopi3.pojo.User">
    insert into user values(#{id},#{name},${age},${salary})
</insert>

调用,注意事务提交,如果需要自动提交,需要显示传递参数为true

@Test
public void test2(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = new User();
    user.setName("ppp");
    user.setAge(99);
    user.setSalary(11111);
    int num = userMapper.addUser(user);
    System.out.println(num);
    // 由于MybatisUtils.getSqlSession调用的是:sqlSessionFactory.openSession();
    // 该方法默认设置自动提交为false,如果需要改为自动提交,
    // 则sqlSessionFactory.openSession(true);即可
    sqlSession.commit();
    sqlSession.close();
}

3.3 Map传参

可以使用map作为入参对象,key作为变量,value作为值来传递参数

接口

int updateUserByMap(Map<String,Object> map);

配置

<update id="updateUserByMap" parameterType="map">
    update user set name=#{param1} where id=#{param2}
</update>

调用

@Test
public void test4(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    Map<String,Object> map = new HashMap<>();
    map.put("param1","xyz");
    map.put("param2",2);
    int num = userMapper.updateUserByMap(map);
    System.out.println(num);
    sqlSession.commit();
    sqlSession.close();
}

3.4 防止SQL注入

防止sql注入,不应该在sql层面进行sql拼接,需要将参数使用#{}去获取,该格式保证参数不会被解析!切记不能去拼接sql,一定要用变量来代替

3.5 模糊查询

<!--方式1,传入时传递`name="李"`-->
<select id="" resultType="">
	select * from user where name like "%"#{name}"%"
</select>
<!--方式2,传入时传递`name="%李%"`-->
<select id="" resultType="">
	select * from user where name like #{name}
</select>

4 配置解析

4.1 environments

可以配置多套环境,但是只能使用一套环境,即default指定的哪个

4.2 transactionManager

事务管理器,Mybatis支持两个:JDBC和MANAGED,一般用前者,后者几乎啥也没做

默认:JDBC

4.3 dataSource

数据源,常用的有c3p0,dbcp,druid

Mybatis的数据源使用jdbc数据源,可以设置三种类型:
unpooled:每次请求打开和关闭连接,不使用连接池
pooled:使用连接池
jndi:传统EJB项目使用这个

默认:POOLED

4.4 properties

该属性可以在外部进行引用配置文件:
在项目的resource目录下,创建db.properties文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ooo?useSSL=false&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456

在mybatis-config.xml中:

<properties resource="db.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

注意:properties放在配置项第一个
配置后如下:

<?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="db.properties"/>

    <environments default="mysql">
        <environment id="mysql">
            <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="com/xiaopi3/dao/UserMapper.xml"></mapper>
    </mappers>
</configuration>

注意:properties属性也能在内部配置字段,但是优先使用外部文件的同名字段

4.5 typeAliases

类型别名,给配置文件中的Java类设置短名字,方便书写和配置

设置方式有两种:
方式一:给每个类起别名

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>

方式二:给每个包下的类起别名,MyBatis 会在包名下面搜索需要的 Java Bean,这时候别名建议为类名首字母小写

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

注意:这种方式下如果不想用类名作为别名,可以使用注解加在类上面:

@Alias("MyUser")
public class User{}

4.5.1 Java类型别名

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

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

注意:下划线表示基础类型,否则为包装类型

4.6 setting

需要了解的主要为以下几个:
在这里插入图片描述
在这里插入图片描述
完整的setting配置:

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

4.7 mapper

mapper映射有几种方式:

<!-- 使用相对于类路径的资源引用 (推荐)-->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL)(不要使用) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 (接口和mapper配置文件需要在同一目录下)-->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 (接口和mapper配置文件需要在同一目录下)-->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

注意:不支持通配符,错误示例:

<mappers>
    <mapper resource="com/xiaopi3/dao/*.xml"></mapper>
</mappers>

如果需要一次导入多个mapper,建议使用包扫描

mapper.xml的配置文件由于需要放在接口同级目录下,可以在resources目录下建立同名包,然后放在该目录下,在编译器期间会自动合并到一起

5 声明周期

生命周期和作用域非常重要,错误使用在并发下会引发严重问题
在这里插入图片描述
SqlSessionFactoryBuilder:

  • 一旦创建了SqlSessionFactory就不需要了
  • 放在局部变量

SqlSessionFactory:

  • 可以理解为数据库连接池
  • 一旦创建就应该在应用运行期间一直存在,使用单例模式或者静态单例模式
  • 放在全局作用域

SqlSession:

  • 连接的一个请求,请求完需要关闭,非线程安全,关闭后会被SqlSessionFactory回收,关闭请求建议放在finnally中
  • 放在方法里
    在这里插入图片描述
    这里每个mapper都是为了执行一个业务

6 resultMap(解决属性名和数据库字段不一致问题)

当javabean的字段和数据库不一致时,会导致查询结果中的字段返回空,原因是,查询到的结果集在于javabean映射时找不到对一个属性!

方法一:sql语句起别名
在这里插入图片描述
方法二:使用resultMap
结果集映射机制
在这里插入图片描述
注意,对于映射中匹配的字段,可以不用显式写出来!
在这里插入图片描述

7 日志

一个数据操作出现异常,排错的时候,日志非常好用。可以使用日志工厂!
支持的工厂:
SLF4J、LOG4J(掌握)、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING(掌握)、NO_LOGGING

7.1 STDOUT_LOGGING(标准日志输出)

在mybatis-config.xml中配置

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

再次执行,则控制台上打印详细日志:

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 450003680.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1ad282e0]
==>  Preparing: select * from user where id=?
==> Parameters: 2(Integer)
<==    Columns: id, name, age, salary
<==        Row: 2, xyz, 2, 1246
<==      Total: 1
User(id=2, name=xyz, age=2, salary=1246)
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1ad282e0]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1ad282e0]
Returned connection 450003680 to pool.

Process finished with exit code 0

7.2 LOG4J

这是外部类,需要先引用依赖

可以控制日志的格式、级别,可以通过配置文件配置,无需修改代码!

7.2.1 引入依赖

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

7.2.2 编写配置文件

在项目resource下创建:log4j.properties文件

# 将等级为DEBUG的日志输出到console和file两个目的地,console和file定义在下面
log4j.rootLogger=DEBUG,console,file

# console定义
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

# file定义
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=lOmb
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

7.2.3 Mybatis配置

<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>

7.2.4 使用

log4j可以输出响应集成的组件的日志,但是如果项自定义使用log4j,可以new一个logger出来:

static Logger logger = Logger.getLogger(当前需要使用的类.class)

logger.info(信息);
logger.debug(信息);
logger.error(信息);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值