SSM之MyBatis 02 —— 配置文件说明、日志工厂、分页(Limit和RowBounds)

系列文章

SSM之MyBatis 01 —— 第一个MyBatis程序、增删改查(模糊查询)

SSM之MyBatis 02 —— 配置文件说明、日志工厂、分页(Limit和RowBounds)

SSM之MyBatis 03 —— 使用注解开发、Lombok、多对一&一对多处理

SSM之MyBatis 04 —— 动态SQL、缓存Cache



四、配置文件说明

官方文档中也有详细解释:https://mybatis.org/mybatis-3/zh/getting-started.html

配置标签有规定顺序:

  • properties
  • settings
  • typeAliases
  • typeHandlers
  • objectFactory
  • objectWrapperFactory
  • reflectorFactory
  • plugins
  • environments
  • databaseIdProvider
  • mappers

1、核心配置文件(mybatis-config.xml)

mybatis-config.xml就是MyBatis的核心配置文件,常把它放在resources目录下。

在这里插入图片描述

在这里插入图片描述
 

2、环境配置(environments)

MyBatis 可以配置成适应多种环境 ,每个environment标签就是一套环境,但但每个 SqlSessionFactory 实例只能选择一种环境(通过default选择默认环境)。 MyBatis默认的事务管理器是JDBC,且默认选择连接池方式。

mybatis-config.xml

<environments default="development">
  <environment id="development">
      .........
      <!-- 事务管理器 包括JDBC(提交和回滚)、MANAGED(这个几乎不做什么) -->
    <transactionManager type="JDBC"/>
      <!-- 数据源:UNPOOLED(无连接池)、POOLED(连接池)、JNDI  -->
    <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>

为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可, 如果忽略了环境参数,那么将会加载默认环境。

//加载自选环境
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
//加载默认环境
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);

3、属性(properties)

先在resources目录下创建一个配置文件properteis

db.properties(根据自己数据库)

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

在mybatis-config.xml中写properties,通过${}引用properties的变量,注意区别mapper.xml中SQL引入变量使用的是#{}。

  • 通过properties标签,可以直接引入外部文件
  • 可以在properties标签中增加属性,比如下面就是用的标签里的name和pwd
  • 如果引入的外部properties文件和标签增加的属性同名,则先使用外部引入文件里的。
<properties resource="db.properties">
    <property name="name" value="root"/>
    <property name="pwd" value="123456"/>
</properties>

<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="${name}"/>
            <property name="password" value="${pwd}"/>
        </dataSource>
    </environment>
</environments>

4、类型别名(typeAliases)

<select id="getUserList" resultType="com.zcy.pojo.User">
    select * from mybatis.user;
</select>

在mapper.xml中写SQL时,实体类需要指定完整的包名,这显得比较麻烦,可以通过别名解决。别名有三种方式。

1、mybatis-config.xml中,用User 代替 com.zcy.pojo.User,

<typeAliases>
    <typeAlias type="com.zcy.pojo.User" alias="User"/>
</typeAliases>

2、mybatis-config.xml中,扫描包下所有实体类,用首字母小写的类名作为其别名

<typeAliases>
    <package name="com.zcy"/>
</typeAliases>

3、在方式2的基础上,在对应的类中加上注解,则用注解的别名

@Alias("User")
public User{
    
    
    .....
}

一般,实体类较少时用方式一,实体类多时用方式二,如果实体类多但又想自定义别名,就方式三。

同时,MyBatis有一些内置的Java类型别名,它们不区分大小写。(就是基本类型前有下划线,包装类则没有,比如int—>_int,而Integer—>intger)

别名 映射的类型
_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
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList

5、设置(setting)

主要用下面三种,后面会具体说明,其他的了解一下就行。

在这里插入图片描述

在这里插入图片描述

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
</settings>

6、其他配置

7、映射器(mappers)

MapperRegister:注册绑定我们的mapper文件

方式一:使用相对于类路径的资源引用【推荐使用】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5FJVAWq-1613964565557)(Mybatis.assets/1613912723800.png)]

<mappers>
    <mapper resource="com/zcy/dao/UserMapper.xml"/>
</mappers>

方式二:使用映射器接口实现类的完全限定类名(通俗点就是,利用接口类找到Mapper)

<mappers>
    <mapper class="com.zcy.dao.UserMapper"/>
</mappers>

注意:mapper文件必须和接口类同名,并且要和接口类放在同一个位置

方式三:将包内的映射器接口实现全部注册为映射器(通俗点就是,指定一个包,将旗下全部接口注册)

<mappers>
    <package name="com.zcy.dao"/>
</mappers>

和方式二一样,需要注意mapper文件要和接口类同名且放在一起

8、生命周期和作用域

生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题!!

1613914035945

SqlSessionFactoryBuilder

  • 目的是生成SqlSessionFctory, 一旦创建了 SqlSessionFactory,就不再需要它了 。
  • 最佳作用域是方法作用域 (即作为局部变量)

SqlSessionFactory

  • 可以把它想象为数据库连接池
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
  • 最佳作用域是应用作用域 (即作为全局变量)
  • 使用单例模式或者静态单例模式(即该变量是唯一的)

SqlSession

  • 它就是连接到连接池的一个请求
  • SqlSession 的实例不是线程安全的,因此是不能被共享的
  • 最佳的作用域是请求或方法作用域 (作为局部变量)
  • 用完之后赶紧关闭,否则资源会被占用
1613914629901

这里面的每一个Mapper就代表一个具体的业务(执行了一件事)!

五、解决属性名和字段名不一致问题

之前使用MyBatis的时候,实体类的属性和数据库中的字段都是一一对应的。

在这里插入图片描述

在这里插入图片描述

当实体类属性和数据库字段不一致怎么办呢?将类的成员名改变
在这里插入图片描述

重新查询时就会出错,名称不一致查询出来就会为空!
在这里插入图片描述

具体原因:

/*我们写的SQL*/
<select id="getUserById" parameterType="int" resultType="User">
	select * from mybatis.user where id = #{id};
</select>
/*实际的SQL和我们User中不一致,就无法将name和username匹配上*/
select id, name, password from mybatis.user where id = #{id};

解决方法:

  1. 比较苯的方法是在SQL中也用别名,将nameas username,passwordas pwd来保证一致
select id, name as username, password as pwd from mybatis.user where id = #{id};

​ 2.使用resultMap(结果集映射)

在mapper中增加resultMap标签

<mapper namespace="com.zcy.dao.UserMapper">
    <!-- 结果集映射 id:该resultMap的名称,type:返回的类型-->
    <resultMap id="UserMapper" type="User">
        <!-- 对于实体类中和数据库字段相同的属性,不需要映射,例如它们都有id -->
        <!-- property:类的属性名,column:数据库的字段名  -->
        <result property="username" column="name"/>
        <result property="pwd" column="password"/>
    </resultMap>

    <!-- 此时就不需要指定resultType   -->
    <select id="getUserById" parameterType="int" resultMap="UserMapper">
        select * from mybatis.user where id = #{id};
    </select>
</mapper>

六、日志

6.1、日志工厂

如果一个数据库操作出现了异常,我们通常会将其作为日志输出,在之前没用MyBatis的时候,我们在实现类中通过sout输出。

曾经:sout、debug

现在:日志工厂

在这里插入图片描述

  • SLF4J
  • LOG4J 【掌握,需要导入包】
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING【掌握,标准日志工厂】
  • NO_LOGGING

在MyBatis的核心配置文件中,添加setting标签

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

比起没用日志,显然多了很多东西,但这些显得比较杂乱,所以我们用后面的Log4j

在这里插入图片描述

6.2、Log4j

什么是Log4j?

  • 可以控制日志信息输送的目的地是控制台、文件、GUI组件…
  • 可以控制每一条日志的输出格式
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程
  • 这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码

1、先导入log4j的包

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

2、log4j.properties,log4j的配置文件(这里使用部分,可百度更详细的)

#将等级为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/zcy.log
#如果文件超过10mb,就分到新文件
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为日志的实现

<!-- 配置日志    -->
<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>

直接使用,和之前没太大区别,但更详细了。

1613958001073

4、简单使用

  1. 在要使用日志的类中导入包 org.apache.log4j.Logger
  2. 创建日志对象 Logger,参数为当前类的class
  3. 控制日志级别进行输出
package dao;

import com.zcy.dao.UserMapper;
import com.zcy.pojo.User;
import com.zcy.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

public class UserMapperTest {
    
    

    static Logger logger = Logger.getLogger(UserMapperTest.class);

    @Test
    public void testLogger(){
    
    
        //常用这三种
        logger.info("info:进入的testLogger");
        logger.debug("debug:进入的testLogger");
        logger.error("error:进入的testLogger");
    }
}


控制台结果:
在这里插入图片描述

同时之前log4j.properties中配置了输出到文件:

1613958675530

七、分页

7.1、Limit 分页

分页是为了减少数据的处理量,在SQL中我们常使用limit进行分页

语法:select * from user limit startIndex, pageSize
例如
select * from user limit 0, 2  表示从第0个数据开始,查两个
select * from user limit 2, 2  表示从第2个数据开始,查两个
select * from user limit 4 表示从第0个数据开始,查到4

使用MyBatis实现分页,其核心仍然是SQL

1、接口

public interface UserMapper {
    
    
    //通过limit实现分页,多个参数用Map
    public List<User> getUserByLimit(Map<String, Integer> map);
}

2、UserMappe.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.zcy.dao.UserMapper">
    <!-- 结果集映射 -->
    <resultMap id="UserMapper" type="User">
        <!-- User类中的id和数据库id同名,而username和password不同名 -->
        <result property="username" column="name"/>
        <result property="pwd" column="password"/>
    </resultMap>

    <!-- 通过Limit分页,map是Map的别名    -->
    <select id="getUserByLimit" parameterType="map" resultMap="UserMapper">
        select * from mybatis.user limit #{startIndex}, #{pageSize} ;
    </select>

</mapper>

3、测试

package dao;

import com.zcy.dao.UserMapper;
import com.zcy.pojo.User;
import com.zcy.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UserMapperTest {
    
    

    static Logger logger = Logger.getLogger(UserMapperTest.class);

    @Test
    public void testLimit(){
    
    
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex", 0);
        map.put("pageSize", 2);
        List<User> userList = userMapper.getUserByLimit(map);

        for (User user : userList)
            System.out.println(user);
        sqlSession.close();
    }
}

结果:

在这里插入图片描述

7.2、RowBounds 分页

不在Mapper的SQL中写分页,而是通过Java代码实现,但这种方式不推荐,因为它不依赖于Mapper了。

1、接口

package com.zcy.dao;

import com.zcy.pojo.User;

import java.util.List;
import java.util.Map;

public interface UserMapper {
    
    
    //通过RowBounds
    public List<User> getUserByRowBounds();
}

2、UserMappe.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.zcy.dao.UserMapper">
    <!-- 结果集映射 -->
    <resultMap id="UserMapper" type="User">
        <!-- User类中的id和数据库id同名,而username和password不同名 -->
        <result property="username" column="name"/>
        <result property="pwd" column="password"/>
    </resultMap>

    <!-- 通过RowBounds分页    -->
    <select id="getUserByRowBounds" resultMap="UserMapper">
        select * from mybatis.user;
    </select>
</mapper>

3、测试

package dao;

import com.zcy.dao.UserMapper;
import com.zcy.pojo.User;
import com.zcy.utils.MyBatisUtils;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UserMapperTest {
    
    

    static Logger logger = Logger.getLogger(UserMapperTest.class);

    @Test
    public void getUserByRowBounds(){
    
    
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        //参数:对应于startIndex,pageSize
        RowBounds rowBounds = new RowBounds(0, 2);
        //之所以说RowBounds过时,就是因为现在已经不再直接调用接口方法的方式,而是用getMapper
        //参数:接口的方法,接口方法的参数,rowBounds分页
        List<User> userList = sqlSession.selectList(
                "com.zcy.dao.UserMapper.getUserByRowBounds", null, rowBounds);

        for (User user : userList)
            System.out.println(user);
        sqlSession.close();
    }
}

结果:

在这里插入图片描述

7.3、分页插件 PageHelpler

具体使用方法:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/README_zh.md

1、引入分页插件(Jar包或者maven)

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.10</version>
</dependency>

2、在mybatis-config.xml配置PageHelper

<!-- 
    plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
    properties?, settings?, 
    typeAliases?, typeHandlers?, 
    objectFactory?,objectWrapperFactory?, 
    plugins?, 
    environments?, databaseIdProvider?, mappers?
-->
<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
        <property name="param1" value="value1"/>
	</plugin>
</plugins>

猜你喜欢

转载自blog.csdn.net/qq_39763246/article/details/113943047