欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

mybatis详解----有这一篇就够了!!!

程序员文章站 2022-06-15 13:55:25
...

mybatis

1. 简介

1.1 mybatis概述

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名为MyBatis 。2013年11月迁移到Github

iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

帮助文档

使用其,需要引入依赖

(x.x.x 指版本 在maven仓库寻找合适版本)

maven

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

持久层

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存 :断电及失
  • 数据库(jdbc)io文件持久化

为什么要有持久化?

​ 因为内存有断电及失的特性。但有些对象我们不能将其丢失,所有出现持久化。

2 第一个mybatis程序

思路

  • 搭建环境
  • 导入mybatis
  • 编写代码
  • 测试

2.1 搭建环境

搭建数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6nI0sYSp-1623898172572)(C:\Users\李晓冰\AppData\Roaming\Typora\typora-user-images\image-20210615143740211.png)]

创建maven项目

导入依赖

2.2 导入mybatis配置文件

编写mybatis的核心配置文件 在resources中创建xml文件 mybatis-config

XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)

<?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="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>
 <!-- 导入mapper.xml配置文件,里面配置了SQL语句和DAO接口的映射关系,每个map都要在核心配置文件注册-->
    <mappers>
        <mapper resource="mapper.xml"/>
    </mappers>
</configuration>

在resource创建mapper包,在此包中根据需要创建与dao成对应的XXXmapper.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">
<!--SQL语句配置文件,需要在mybatis配置文件中进行加载-->

   <!--mapper标签用于做SQL语句和方法之间的映射-->

   <!--一个mapper对应一个类,namespace里面写的是dao接口的完整路径-->

   <mapper namespace="com.nuc.dao.UserDao">

       <!--select的id是方法名-->

       <!--resultType是查询的结果的一种映射,User类的属性与列名完全一致(bean类),所以查询的结果会转换成User类-->

       <select id="getAll" resultType="User类的完整路径:包名.类名">

           /具体的sql语句/

           select * from usertest

       </select>

   </mapper>

2.3 编码

pojo层

写入一个user类

dao层----与mapper对应 要在namespace写入对应全类名

import com.nuc.pojo.User;
 
import java.util.List;
 
public interface UserDao {
    List<User> getAll();

Service层

ServiceImpl层

2.4 测试

public class Test {
    public static void main(String[] args) throws Exception {
        //加载配置文件
        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
        //得到sqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory build = builder.build(reader);

        //得到sqlSession
        SqlSession sqlSession = build.openSession();
        //操作sql  传入参数:类名.方法名
        List<User> list = sqlSession.selectList("com.nuc.dao.UserDao.getAll");
        //遍历
        for (User u : list){
            System.out.println(u);
        }

        //关闭资源
        sqlSession.close();
        reader.close();
    }
}

3 crud(增删改查)

1 insert

增加语句;

  • id:就是对应的namespace中的方法名;
  • resultType : Sql语句执行的返回值;
  • parameterType : 参数类型;
<!--namespace=绑定一个指定的Dao/Mapper接口-->
<mapper namespace="com.nuc.dao.UserDao">
    <select id="getAll" resultType="com.nuc.pojo.User" >
        select * from USER
    </select>
</mapper>

​ 步骤 :

  1. 编写接口
public interface UserMapper {
    //插入用户
    public void addUser(User user);
}
  1. 编写对应的mapper中的sql语句

    <insert id="addUser" parameterType="com.nuc.pojo.User">
        insert into user (id,name,password) values (#{id}, #{name}, #{password})
    </insert>
    
    3. 测试
    
    @Test
    public void test2() {
       SqlSession sqlSession = MybatisUtils.getSqlSession();
       UserMapper mapper = sqlSession.getMapper(UserMapper.class);
       User user  = new User(1,"望埠","123");
       mapper.addUser(user);
       //增删改一定要提交事务
       sqlSession.commit();
    
       //关闭sqlSession
       sqlSession.close();
    }
    
    

2. select

   <select id="getAll" resultType="com.nuc.pojo.User">
        select * from USER
    </select>

3. update

 <update id="updateUser" parameterType="User">
        update user set name=#{name},pwd=#{pwd} where id=#{id}
    </update>

4. Delete

<delete id="delectUser" parameterType="java.lang.String">
        delete from user where name = #{name}
    </delete>

注意 增删改一定要提交事务:sqlSession.commit();

Map

当我们的实体类,或数据库中的表参数过多,我们应该使用map

 <insert id="addUser2" parameterType="map">
        insert into user (id,name)
        values (#{userid},#{username});
    </insert>

测试:

    @Test
    public void test02() throws IOException {
        //加载配置文件
        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
        //得到sqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory build = builder.build(reader);

        //得到sqlSession
        SqlSession sqlSession = build.openSession();
        Map<String,Object> map = new HashMap<>();
        map.put("userid",5);
        map.put("username", "jj");
        sqlSession.insert("com.nuc.dao.UserDao.addUser2",map);
        sqlSession.commit();
//关闭sqlSession
        sqlSession.close();
    }

注意 :提交事务

Map传递参数,直接在sql中取出key即可! 【parameter=“map”】

对象传递参数,直接在sql中取出对象的属性即可! 【parameter=“Object”】

只有一个基本类型参数的情况下,可以直接在sql中取到

多个参数用Map , 或者注解!

模糊查询

1 在java代码执行时,传递通配符

接口:

List<User> selectlike(String value);

map

<select id="selectlike" resultType="com.nuc.pojo.User" parameterType="java.lang.String">
        select * from user where name like #{value}
    </select>

测试:

@Test
public void test() throws IOException {

    //加载配置文件
    Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
    //得到sqlSessionFactoryBuilder
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory build = builder.build(reader);

    //得到sqlSession
    SqlSession sqlSession = build.openSession();
    List<User> list = sqlSession.selectList("com.nuc.dao.UserDao.selectlike","%李%");

    for (User user : list) {
        System.out.println(user.toString());
    }

    //关闭sqlSession
    sqlSession.close();
}

2.在sql拼接使用通配符

<select id="selectlike" resultType="com.nuc.pojo.User" parameterType="java.lang.String">
        select * from user where name like “%”#{value}“%”
    </select>

mybatis的xml配置

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

configuration(配置)

1.环境配置environments

记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

<environments default="development">
    <!--通过default  来选择需要的环境的id来控制环境-->
  <environment id="development">
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <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>

2.事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]")

3.数据源(dataSource)

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

  • 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。

有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]")

mybatis默认事务管理器jdbc 连接池 POOLED

4. 属性(properties)

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置:

步骤:

  1. 可以在resource中创建db.properties文件,用于存放属性
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&appserverTimezone=UTC
username =root
password = root
2. 在核心配置文件映入
 <!--引入外部配置文件-->   
<properties resource="db.properties"></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="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
  • 可以直接引入外部文件
  • 可以在其中增加一些属性配置
  • 如果两个文件有同一个字段,优先使用外部配置文件的

5. 类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。如mapper中返回值类型的全限定类名

<!--给实体类起名-->
<typeAliases>
    <typeAlias type="com.nuc.pojo.User" alias="user"></typeAlias>
</typeAliases>

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
    <package name="com.nuc.pojo"  />
</typeAliases>

扫描实体类的包,他的默认别名就是这个类的类名,首字母小写

但若在实体类上有注解,则别名为其注解值。见下面的例子:

@Alias("author")
public class Author {
    ...
}

6设置(settings)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

设置setting详情

7.映射器(mappers)

MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。

现在主要用以下方法实现

第一种

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="com/nuc/Mapper/UserMapper.xml"/>
  <mapper resource="com/nuc/Mapper/PersonMapper.xml"/>
 
</mappers>

第二种

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="com.nuc.pojo"/>
</mappers>

第三种

<!--每一个Mapper.xml都需要在MyBatis核心配置文件中注册-->
<mappers>
    <mapper class="com.kuang.dao.UserMapper"/>
</mappers>

**注意点:**第二种和第三种方法

  • 接口和他的Mapper配置文件必须同名
  • 接口和他的Mapper配置文件必须在同一个包下

8.生命周期和作用域

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

SqlSessionFactoryBuilder:

  • 一旦创建了SqlSessionFactory,就不再需要它了

  • 局部变量

    SqlSessionFactory:

  • 说白了就可以想象为:数据库连接池
    SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建一个实例。因此SqlSessionFactory的最佳作用域是应用作用域(ApplocationContext)。

  • 最简单的就是使用单例模式或静态单例模式。

    SqlSession:

  • 连接到连接池的一个请求

  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。

  • 用完之后需要赶紧关闭,否则资源被占用!

解决用户属性名与数据库字段名不匹配问题

当累的属性为:

 private int id;
    private String name;
    private String password;

数据库字段名为

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wAkPk4dR-1623898172574)(C:\Users\李晓冰\AppData\Roaming\Typora\typora-user-images\image-20210616184127087.png)]

用User接收无法接收到password属性

解决 方法:

  1. 起别名

     <select id="getAll" resultType="aaa">
            select id,name,pwd as password from USER
        </select>
    
  2. 使用resultMap

resultMap是一个结果集映射

<!--结果集映射-->
<resultMap id="UserMap" type="User">
    <!--column数据库中的字段,property实体类中的属性-->
   <!-- 相同的可以不去写,只用关注不同的
<result column="id" property="id"></result>
<result column="name" property="name"></result>-->
    <result column="pwd" property="password"></result>
</resultMap>

<select id="getUserList" resultMap="UserMap">
    select* from USER
</select>
  • resultMap 元素是 MyBatis 中最重要最强大的元素。

  • ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

  • ResultMap 的优秀之处——你完全可以不用显式地配置它们。

  • 如果这个世界总是这么简单就好了(尤其是找对象)

日志

如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的纠错助手

曾经:sout输出、debug

现在:日志工厂

  • SLF4J
  • **LOG4J ** (使用要导包)
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING
  • NO_LOGGING

在MyBatis中具体使用哪一个日志实现,在设置中设定

STDOUT_LOGGING

<!-- 标准的日志工厂实现-->
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

注意 是logImpl ,Impl的i是大写的,不能有一点错,也不能有空格。

log4j

  1. 简介:

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

  1. 使用

    2.1 导包

    地址

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

    在resources中配置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/lxb.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
    
    1. 3在核心配置文件配置
    <settings>
            <setting name="logImpl" value="LOG4J"/>
        </settings>
    

    2.4 在要使用log4j的類中使用

    import org.apache.log4j.Logger;
    import org.junit.jupiter.api.Test;
    
    public class UserTest {
        static Logger logger = Logger.getLogger(UserTest.class);  //括號内跟本类的。class
        @Test
        public void test(){
            logger.info("info: 测试log4j");
            logger.debug("debug: 测试log4j");
            logger.error("error:测试log4j");
        }
    }
    
    

    运行完后生成log4j文件

分页

1. 使用Limit分页

SELECT * from user limit startIndex,pageSize 

下面是每页显示4个 从0开始查

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4QuVIsmn-1623898172576)(C:\Users\李晓冰\AppData\Roaming\Typora\typora-user-images\image-20210616204351239.png)]

# 相当于SELECT * from user limit 0,3

SELECT * from user limit 3

2. 使用rowbounds分页

不再使用SQL实现分页,通过java代码实现

接口

List<User> getUserByRowBounds();

mapper

<select id="getUserByRowBounds">
    select * from user
</select>

测试

@Test   
public void getUserByRowBounds(){
         //加载配置文件
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            //得到sqlSessionFactoryBuilder
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory build = builder.build(reader);

            //得到sqlSession
            SqlSession sqlSession = build.openSession();
        //RowBounds实现  从下表一开始,每页显示2个
        RowBounds rowBounds = new RowBounds(1, 2);
        //通过Java代码层面实现分页
        List<User> userList = sqlSession.selectList("com.kaung.dao.UserMapper.getUserByRowBounds", null, rowBounds);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

3.通过插件

mybatis分页插件pageHelper

链接

使用说明文档

说明文档

使用注解开发

相关标签: mybatis