0


MyBatis入门(一)MyBatis介绍和入门案例

一.MyBatis介绍

1.什么是框架?

框架即一个半成品软件。开发者从头开发一个软件需要花费大量精力,于是有一些项目组开发出半成品软件,开发者在这些软件的基础上进行开发,这样的软件就称之为框架。

如果将开发完成的软件比作是一套已经装修完毕的新房,框架就好比是一套已经修建好的毛坯房。用户直接购买毛坯房,保证建筑质量和户型合理的同时可以进行风格的自由装修。

使用框架开发的好处:

  • 省去大量的代码编写、减少开发时间、降低开发难度。
  • 限制程序员必须使用框架规范开发,增强代码的规范性,降低程序员之间沟通及日后维护的 成本。
  • 将程序员的注意力从技术中抽离出来,更集中在业务层面。

使用框架就好比和世界上最优秀的软件工程师共同完成一个项目,并且他们完成的还是基础、全局的工作。

2.什么是ORM框架?

ORM(Object Relationl Mapping),对象关系映射,即在数据库和对象之间作映射处理。

之前我们使用JDBC操作数据库,必须手动进行数据库和对象间的数据转换。

如下代码:

// 新增方法,将对象转为sql语句字段
public void AddUser(User user) throwsException {
    Class.forName("com.mysql.jdbc.Driver");
    Connection connection =DriverManager.getConnection("jdbc:mysql://localhost:3306     /mybatis?characterEncoding=utf8","root", "root");
    String sql = "INSERT INTO user values(null,?,?,?,?)"; 
    PreparedStatement preparedStatement =connection.prepareStatement(sql);
    preparedStatement.setString(1,user.getName());
    preparedStatement.setInt(2,user.getAge());
    preparedStatement.setString(3,user.getAddress());
    preparedStatement.setString(4,user.getSex());
    preparedStatement.executeUpdate();
    // 省略资源关闭...
}

 // 查询方法,将数据库结果集转为对象
 public List<User> findAllUser() throws Exception {
    Connection connection =DriverManager.getConnection("jdbc:mysql://localhost:3306      /mybatis?characterEncoding=utf-8", "root", "root");
    PreparedStatement preparedStatement =connection.prepareStatement("select * from
    user");
    ResultSet resultSet =preparedStatement.executeQuery();

    //遍历查询结果集
    List<User> users = new ArrayList<>();
    while(resultSet.next()){
        // 拿到每一列数据
        int id = resultSet.getInt("id");
        String name =resultSet.getString("name");
        int age = resultSet.getInt("age");
        String address =resultSet.getString("address");
        String sex =resultSet.getString("sex");
        // 将数据封装到对象中
        User user = new User();
        user.setId(id);
        user.setName(name);
        user.setAge(age);
        user.setAddress(address);
        user.setSex(sex);
        users.add(user);
   }
   // 省略资源关闭...
   return users; 
}

这段代码中,数据库数据与对象数据的转换代码繁琐、无技术含量。而使用ORM框架代替JDBC后,框架可以帮助程序员自动进行转换,只要像平时一样操作对象,ORM框架就会根据映射完成对数据库的操作,极大的增强了开发效率。

3.什么是MyBatis?

MyBatis是一个半自动的ORM框架,其本质是对JDBC的封装。使用MyBatis不需要写JDBC代码,但需要程序员编写SQL语句。之前是apache的一个开源项目iBatis,2010年改名为MyBatis。

补充:

Hibernate也是一款持久层ORM框架,多年前的市场占有率很高,但近年来市场占有率越来越低。

MyBatis与Hibernate的比较:

  • MyBatis是一个半自动的ORM框架,需要手写SQL语句。
  • Hibernate是一个全自动的ORM框架,不需要手写SQL语句。
  • 使用MyBatis的开发量要大于Hibernate。

为什么Hibernate市场占有率越来越低:

  • 对于新手学习Hibernate时间成本比MyBatis大很多,MyBatis上手很快。

  • Hibernate不需要写SQL语句是因为框架来生成SQL语句。对于复杂查询,开发者很难控制生 成的SQL语句,这就导致SQL调优很难进行。

  • 之前的项目功能简单,数据量小,所以使用Hibernate可以快速完成开发。而近年来项目的 数据量越来越大,而互联网项目对查询速度要求也很高,这就要求我们一定要精细化的调整 SQL语句。此时灵活性更强,手动编写SQL语句的MyBatis慢慢代替了Hibernate使用。

  • 在高并发、大数据、高性能、高响应的互联网项目中,MyBatis是首选的持久框架。而对于对性能要求不高的比如内部管理系统等可以使用Hibernate。

二.MyBatis入门案例

1.环境搭建

1

**(1)将SQL文件导入数据库 **

打开Navicat,右键locahost,新建数据库,

双击mybatis数据库,使其连接,然后右键-->运行SQL文件,选择已有的数据库sql文件导入

可以看见导入成功!右键刷新之后可以看见导入的表。

2

**(2)创建maven工程,引入依赖 **

创建一个空项目

再在此空项目下创建一个不设置Archetype的maven项目,

在 mybatisDemo1工程中的pom.xml文件中配置依赖<dependencies>如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>mybatisDemo1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--必须引入的包-->
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

        <!--不是必须引入的包,但是为了方便我们使用而引入-->
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <!--log4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
    </dependencies>

</project>

(3)创建mybatis核心配置文件SqlMapConfig.xml

主要配置如何连接数据库

放在mybatisDemo1的src/main/resources中

如果"http://mybatis.org/dtd/mybatis-3-config.dtd"url地址报红色,那么就如下解决:

File-->Setting-->搜索DTD,找到Schemas and DTDs,点击加号,将路径添加到其中即可。

SqlMapConfig.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"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

**(4)将log4j.properties文件放入src/main/resources中,让控制台打印SQL语句。 **

log4j.properties文件内容:

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=debug, CONSOLE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
#log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%d{MM/dd HH:mm:ss}] %-6r [%15.15t] %-5p %30.30c %x - %m\n

**5 **

**(5)创建实体类 **

User.java:

package com.first.pojo;

public class User {
    private int id;
    private String username;
    private String sex;
    private String address;

    public User() {
    }

    public User(int id, String username, String sex, String address) {
        this.id = id;
        this.username = username;
        this.sex = sex;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

项目结构:

2.创建持久层接口和映射文件

项目结构:

1

(1)在java目录创建持久层接口

package com.first.mapper;

import com.first.pojo.User;

import java.util.List;

public interface UserMapper {
    //每一个方法对应一个sql语句
    //接口函数由映射文件实现
    List<User> findAll();
}

(2)在resource目录创建UserMapper的
映射文件,注意目录要和对应接口一致,也是com/first/mapper,创建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>后:

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

<!--        namespace设置映射的文件-->
<mapper namespace="com.first.mapper.UserMapper">
<!--
    id是方法名;
    resultType表示结果的对象,即列表的泛型;
    查找用select标签 -->
    <select id="findAll" resultType="com.first.pojo.User">
        select * from user
    </select>
</mapper>

(3)将映射文件配置到mybatis核心配置文件SqlMapConfig.xml中 ,因为项目启动时,先加载核心配置文件SqlMapConfig.xml,只有注册到核心配置文件SqlMapConfig.xml中的配置文件才可以加载到。

在SqlMapConfig.xml的<configuration>标签中添加如下代码注册映射文件

<!--    注册映射文件-->
    <mappers>
        <mapper resource="com/first/mapper/UserMapper.xml"></mapper>
    </mappers>

**映射文件注意事项: **

  • 映射文件要和接口名称相同。
  • 映射文件要和接口的目录结构相同。
  • 映射文件中namespace属性要写接口的全名。
  • 映射文件中标签的id属性是接口方法的方法名。
  • 映射文件中标签的resultType属性是接口方法的返回值类型。
  • 映射文件中标签的parameterType属性是接口方法的参数类型。
  • 映射文件中resultType、parameterType属性要写全类名,如果是集合类型,则写其泛型的全类名。

3.测试持久层接口方法

如第二节配置之后,mybatis自己就利用代理对象帮我们实现了接口方法,所以接下来直接测试就行了!

package com.first.mapper;

import com.first.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;

public class TestUserMapper {
    @Test
    public void testFinaAll() throws Exception{
        //(1)读取核心配置文件
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
        //(2)创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(is);
        //(4)SqlSessionFactory对象获取SqlSession对象
        SqlSession session = factory.openSession();
        //(5)SqlSession对象获取代理代理对象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //(6)代理对象执行方法
        List<User> all=userMapper.findAll();

        //(7)释放资源
        session.close();
        is.close();
    }
}

点击左侧绿色按钮开始测试:

遇到一个异常:

Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration
java.io.IOException: Could not find resource com/first/mapper/UserMapper.xml

找了找发现我之前测试类命名错误了(命名成UserMapper),所以我修改了名称为TestUserMapper,但是idea自动帮我把UserMapper.xml里的UserMapper也改成了TestUserMapper,但是发现还是不行,于是参考了下面的文章解决了bug!

解决mybatis中:Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration_水巷石子的博客-CSDN博客

运行结果:

4.MyBatis核心对象及工作流程

*MyBatis***核心对象 **

SqlSessionFactoryBuilder

SqlSession工厂构建者对象,使用构造者模式创建SqlSession工厂对象。

SqlSessionFactory

SqlSession工厂,使用工厂模式创建SqlSession对象。

SqlSession

该对象可以操作数据库,也可以使用动态代理模式创建持久层接口的代理对象操作数据库。

Mapper

持久层接口的代理对象,他具体实现了持久层接口,用来操作数据库。

*MyBatis***工作流程 **

1

  1. 创建SqlSessionFactoryBuilder对象
  2. SqlSessionFactoryBuilder对象构建了SqlSessionFactory对象:构造者模式
  3. SqlSessionFactory对象生产了SqlSession对象:工厂模式
  4. SqlSession对象创建了持久层接口的代理对象:动态代理模式
  5. 代理对象操作数据库

5.使用SqlSession操作数据库

除了代理对象能够操作数据库,SqlSession也能操作数据库。只是这种方式在开发中使用的较少(了解即可),接下来我们使用SqlSession操作数据库:

在TestUserMapper中添加一个测试函数testFinaAll2(),如下:

package com.first.mapper;

import com.first.mapper.UserMapper;
import com.first.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;

public class TestUserMapper {
    @Test
    public void testFinaAll() throws Exception{
        //(1)读取核心配置文件
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
        //(2)创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(is);
        //(4)SqlSessionFactory对象获取SqlSession对象
        SqlSession session = factory.openSession();
        //(5)SqlSession对象获取代理代理对象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //(6)代理对象执行方法
        List<User> all=userMapper.findAll();
        all.forEach(System.out::println);

        //(7)释放资源
        session.close();
        is.close();
    }
    @Test
    public void testFinaAll2() throws Exception{
        //(1)读取核心配置文件
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
        //(2)创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(is);
        //(4)SqlSessionFactory对象获取SqlSession对象
        SqlSession session = factory.openSession();
        //(5)SqlSession对象直接操作数据库
        //参数是持久层接口全类名+方法名
        List<User> users=session.selectList("com.first.mapper.UserMapper.findAll");
        users.forEach(System.out::println);

        //(6)释放资源
        session.close();
        is.close();
    }
}

输出和上节一样。

6.Mapper动态代理原理

接下来我们通过源码,了解MyBatis的Mapper对象究竟是怎么生成的,他又是如何代理接口的方法。

**获取代理对象 **

点开测试类的 getMapper 方法,查看该方法最终调用了什么方法。

当看到 Proxy.newProxyInstance 时,可以确定 getMapper 方法最终调用的是JDK动态代理方法,且使用MapperProxy类定义代理方式

**查看代理方式 **

点开MapperProxy类,查看invoke方法,查看代理对象是如何工作的。

可以看到,MapperProxy调用了MapperMethod的execute方法定义了代理方式,且底层调用的是SqlSession的方法,根据映射文件标签不同调用不同的SqlSession方法。

结论:

  • SqlSession的getMapper方法,最终是调用的是JDK动态代理方法,生成一个代理对象,类型就是传入的接口类型。
  • MapperProxy对象通过调用MapperMethod的execute方法定义了代理方式,该方法的底层调用的是SqlSession的方法。
标签: javaEE MyBatis sql

本文转载自: https://blog.csdn.net/weixin_44593822/article/details/124816782
版权归原作者 深海鱼肝油ya 所有, 如有侵权,请联系我们删除。

“MyBatis入门(一)MyBatis介绍和入门案例”的评论:

还没有评论