IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Mybatis(一) -> 正文阅读

[Java知识库]Mybatis(一)

1. Mybatis必知

简介

  • 历史小知

市面上现今用的最多的是Mybatis3.4+的版本,以前的Mybatis2版本的并不叫叫做ibatis,包括现在使用mybatis导入的包很多都是经常能看到
import org.apache.ibatis.*下的一些包,这是因为在最初的时候是由apache开源基金会来维护,后来2010年团队转战到谷歌旗下,谷歌为区别改名为Mybatis,再后来2013年迁移到github上,现在招聘上所说熟练掌握ibatisMybatis其实都是同一个框架,并且现在想要深入了解Mybatis的源码,需要去github上找。

  • 什么是Mybatis(Mybatis的优点)

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

持久层框架:操作数据库的框架

ORM:对象关系映射,Object Relation Mapping(数据库一条记录对应一个对象)

与Hibernate共性与区别

在此之前我们学习的操作数据库的方式有以下:

  • 原生JDBC
  • DBUtils(工具类并不是框架)
  • SpringJDBCTemplate工具
  • Hibernate框架(SpringDataJPA为典型实现)
  • 从前处理数据库的方式如下:
    在这里插入图片描述特点:功能简单,sql编写在java代码中,硬编码,高耦合,维护比较复杂
  • 使用框架(Hibernate
    Hibernate:全自动ORM框架,旨在消除sql语句,通过想xml配置(或注解)javaBean和数据库表关系,框架自动生成sql语句,如下:
    在这里插入图片描述

问题:

  • sql为框架自动生成,难以sql优化
  • 特殊场景需要定制sql,(可以学习Hibernate的HQL)
  • 全字段全映射问题,数据库字映射模糊,比如只需要查出一个字段,Hibernate会查出所有字段
  • 使用框架(Mybatis)
    Mybatis为半自动ORM映射的轻量级框架,弥补Hibernate的不足,将编写sql提取出来,交给人为操作。
    在这里插入图片描述优点:人为操作sql,可以对sql进行优化管理,掌握sql就可以,并且层次分明,sql与java代码分开,一个专注于数据一个专注于业务。
    缺点:需要对sql有一定的熟练度

2. 原生Mybatis

1.准备好maven的环境,pom.xml如下

  <dependencies>
    <!--单元测试-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.6</version>
    </dependency>

    <!--数据库驱动jar包-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.49</version>
    </dependency>

    <!--引入mybatis包----------------------->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.10</version>
    </dependency>
    
  </dependencies>

2.创建实体类,可使用lombok

package com.sang.entity;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class Student {
    private Integer id;
    private String name;
    private String email;
    private Integer age;
}

3.创建数据库表,在ssm数据库下创建student表:

create table student(
	id int(11) primary key auto_increment,
	name varchar(100),
	email varchar(100),
	age int(11)
);

4.在resources下创建maper文件编写sql语句

<?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="StudentMapper">

</mapper>

接着在mapper下编写sql语句

<?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="StudentMapper">
    <select id="selectStudent" resultType="student">
        select * from student where id = #{id}
    </select>
</mapper>

5.配置Mybatis的config文件

<?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="dev">
        <environment id="dev">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="StudentMapper.xml"/>
    </mappers>
</configuration>

说明

  • environments 下可以编写多个environments配置,作用在于开发环境,生产环境,Mysql,orcle数据库等
  • transactionManager 配置的是事务管理器,JDBC
  • dataSource -type表示的是数据库连接方式,POOLED表示数据库连接池
  • dataSource 中配置的是数据库连接的属性

6.编写测试类,在src/test/java下创建单元测试类并创建方法和@Test

	@Test
    public void HelloWorld() throws IOException {
        InputStream inputStream=Resources.getResourceAsStream("mybatisConfig/mybatisConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = sqlSessionFactoryBuilder.build(inputStream);
        SqlSession sqlSession = factory.openSession();
        Student student= (Student)sqlSession.selectOne("StudentMapper.selectStudent", 1);
        System.out.println(student);
        sqlSession.close();
    }

Maven下mapper文件的位置问题

这里需要说明以下几点:

  • namespace是命名空间,这个mapper文件的唯一标识符
  • xml文件的位置,这里直接定义在resources下,如果想放在src/main/java下,则需要在maven下添加如下代码,目的在于让maven加载打包源文件下的非java文件(重点)
<build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>  
    </resources>
  </build>

说明:

SqlSessionFactoryBuilder 根据Mybatis的config文件的流对象创建出一个sqlsession工厂对象,该对象调用openSession()方法得到sqlsession对象,sqlSession对象通过selectOne来选取方法,其中第一个参数是哪一个mapper文件的哪一个sql方法,定位标准是mapper文件的namespace的值和内部的sql方法的id值,第二个值是传递的参数,这样得到的是一个Object对象,强转成需要的对象类型,打印出来。
在这里插入图片描述
openSession()方法中如果传入true,则不需要自己提交事务,不写则默认需要自己提交事务,即sqlsession.commit()

3.接口式编程

将原生的方式进行大大简化
1.创建实体类的接口StudentDao(码略)
2.在resources下创建与接口名相同的文件夹,并在这其中创建一个mapper文件

<?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.sang.dao.StudentDao">
</mapper>

3.在mybatis的config文件中mappers下注册mapper文件的位置,可以用package注册某一包下所有mapper文件

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

4.在mapper下编写sql语句

    <select id="findStudentById" resultType="student">
        select * from student where id=#{id}
    </select>

5.在测试类中编写测试类进行测试

@Test
    public void Test() throws IOException {
        InputStream inputStream= Resources.getResourceAsStream("mybatisConfig/mybatisConfig.xml");
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sessionFactory = factoryBuilder.build(inputStream);
        SqlSession sqlSession = sessionFactory.openSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Student student = studentDao.findStudentById(1);
        System.out.println(student);
        sqlSession.close();
    }

注意:

  • namespace必须指定接口的全类名
  • 注册的mapper文件一定要和接口名除了扩展名外其余要一模一样!!!!
  • mappers标签下,需要用package标签来注册指定包下的所有mapper文件
  • sqlSession.getMapper()这里sqlsession根据接口的字节码对象来生成一个接口的代理对象,之后可以用这个代理对象来进行实现方法。

接口实现的动态代理

        SqlSession sqlSession = sessionFactory.openSession();
        StudentDao studentDao= sqlSession.getMapper(StudentDao.class);
       	Student student = studentDao.findStudentById(1);

这里 studentDao可以调用findStudentById(1) 这个方法,说明 studentDao是个对象,因为对象才具有方法行为实现啊。StudentDao是接口,接口是不能实例化的,更没有具体方法实现。我们并没有定义一个类,让它实现StudentDao 接口,而在这里它只是通过调用sqlSession.getMapper() 所得到的。由此,我们可以推断:肯定是sqlSession.getMapper() 方法内部产生了StudentDao 的实现类。有什么技术可以根据StudentDao 接口生成了一个实现类呢?想到这里,对于有动态代理

动态代理

为什么要使用动态代理?可以在不修改别代理对象代码的基础上,通过扩展代理类,进行一些功能的附加与增强。我们先看看传统的JDK动态代理:

1.首先有一个接口

public interface Add{
    void add(int i, int j);
}

2.然后是接口的实现类

public class AddImpl implements Add{
    @Override
    public void add(int i, int j) {
        System.out.println("result = " + (i + j));
    }
}

3.代理类实现InvocationHandler

public class AddProxy implements InvocationHandler {
    private Object target;
    //总要让我知道要代理谁吧:构造方法中把传入一个代理类的实例
    public AddProxy (Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("====== 前方法() ======");
        method.invoke(target, args);
        System.out.println("====== 后方法() ======");
        return null;
    }
}

4.拿到代理对象,操作接口方法

public class test {
    public static void main(String[] args) {
        InvocationHandler handler = new AddProxy (new AddImpl());
        Add addProxy =
                (Add)Proxy.newProxyInstance(Add.class.getClassLoader(),
                        new Class[]{Add.class},
                        handler);
        addProxy.add(10,20);
    }
}

Proxy.newProxyInstance()方法有三个参数

  1. 类加载器(Class Loader)

  2. 需要实现的接口数组

  3. InvocationHandler接口所有动态代理类的方法调用,都会交由InvocationHandler接口实现类里的invoke()方法去处理。这是动态代理的关键所在。

回到我们之前的问题,我们并没有接口实现类,那没有实现类还为什么还能调用方法操作。其实是这样的:

操作数据库主要是通过SQL语句,那么只要找到SQL语句执行的方法然后执行这个方法就OK了!

Maven下mapper文件的位置问题(注意)

有的同学在接口式编程时处理mapper文件经常会碰到找不到接口方法等之类的问题,下面小子来说明一下出现的问题以及解决方案,希望能帮助到大家。
首先,说明一下Maven对resources目录下资源文件处理方式以及maven的目录结构

  • maven的目录结构
    在这里插入图片描述maven打包后classes目录结构为:
    在这里插入图片描述resources中的资源文件会被直接放到类路径的根路径下(与类代码同级)

问题:默认情况下,会将src/main/resources下的文件原封不动的放到target/classes下,而src/main/java中的非java文件不会处理

解决方案一(添加maven资源文件处理)

  • 将mapper文件和接口代码放在一起如:
    在这里插入图片描述此时由于maven不会处理src/main/java中的xml文件,则需要在Maven的 配置文件pomm.xml文件中添加如下配置
<resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
</resources>

运行测试类时会出现找不到mybatisConfig文件的错误,这时我们打开target的classes文件夹,发下原本的resources下的资源文件并没有被maven放进来

  • 默认情况下,会将src/main/resources下的文件原封不动的放到target/classes下,而src/main/java中的非java文件不会处理
  • 但是,如果我们配置了<resources>标签对java目录下非java文件处理的配置后,Maven的默认处理方式就会被修改,从而不对src/main/resources下资源文件进行处理!!!
  • 那么,对java目录下资源进行处理,也能对resources目录下进行处理!

改善:

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*</include>
        </includes>
      </resource>
    </resources>
  </build>

解决方案二(优化选择)

根据Maven的目录结构分析
在这里插入图片描述我们可以将mapper文件的包结构和接口包结构设置成一样,也就是在resources目录下创建 与接口文件相同的文件夹,那么在生成的target目录中xml和接口文件就是在同一目录中了
如图:
在这里插入图片描述

4.IDEA下配置两种dtd的xml约束文件

mapper的纯净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="">
</mapper>

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="dev">
        <environment id="dev">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
    </mappers>
</configuration>

在实际开发中xml的文件记不住,也不会去记他,在我们的IDEA中就提供了非常方便的方法来创建纯净的xml文件

  • 首先将mapper.xml内的代码复制,然后点击左上角File->Settings->Editor->File And Code Templates

  • 点击左边的侧边栏上面的+号,再输入想要辨别的文件名和文件格式
    在这里插入图片描述

  • 将复制在粘贴板的代码粘贴进去,点击保存,同理config文件创建一样下面我们来右击创建一个mapper效果
    在这里插入图片描述

注意

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

http://mybatis.org/dtd/mybatis-3-config.dtd是该xml文件的约束文件,一般都有互联网能下载下来,IDEA按住ctrl点击进入后能看到约束内容,其中规定了该xml标签的位置顺序,如果顺序错了,IDEA会出现爆红现象

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:30:26  更:2021-07-11 16:31:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 10:22:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码