MyBatis教程

原文链接:MyBatis教程(看这一篇就够了)入门到精通

环境

  • JDK1.8
  • MySql8.0
  • maven3.6
  • IDEA

SSM框架:配置文件

官方文档:mybatis.org/mybatis-3/z…

一、简介

(一)什么是mybatis

  • MyBatis 是一款优秀的持久层框架

  • 它支持自定义 SQL、存储过程以及高级映射。

  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

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

从哪使用mybatis

  • maven仓库
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>

(二)持久层

数据持久化

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

为什么需要持久化?

  • 不能丢掉的对象
  • 节约内存

定义:

  • 完成持久化工作的代码块
  • 层的界限十分明显

(三)使用mybatis的原因

  • 帮助程序员将数据存入到数据库中
  • 方便
  • jdbc过于复杂,简化框架。
  • 实现自动化
  • 不使用框架也能写网站,但是使用框架更容易上手
  • 优点
    • 简单易学
    • 灵活
    • sql和代码的分离,提高代码的可维护性
    • 提供映射标签,支持对象关系组件维护
    • 提供xml标签,支持编写动态sql

二、第一个MyBatis程序

==搭建环境----->导入MyBatis--->编写代码--->测试==

(一)搭建环境

搭建数据库

复制代码
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE DATABASE `mybatis`;

CREATE TABLE `user`(
    `id` INT(20) NOT NULL,
    `name` VARCHAR(30) DEFAULT NULL,
    `pwd` VARCHAR(30) DEFAULT NULL,
    PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,'狂神','123456'),
(2,'张三','abcdef'),
(3,'李四','987654');
复制代码

新建项目

  1. 新建一个普通的maven项目

  2. 删除src目录

  3. 导入maven依赖

复制代码
    <dependencies>
<!--        mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
<!--        junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
<!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
    </dependencies>
复制代码

(二)创建一个模块

  • 创建mybatis的核心配置文件
复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration核心配置文件-->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=YTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
</configuration>
复制代码
  • 编写mybatis工具类
复制代码
// SqlSessionFactory--> SqlSession
public class MybatisUntils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            //获取 SqlSessionFactory对象
            String resource = "org/mybatis/example/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}
复制代码

(三)编写代码

  • 实体类
复制代码
public class User {
    private int id;
    private String name;
    private String pwd;

    public User() {
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}
复制代码
  • Dao接口
public interface UserDao {
    List<User> getUserList();
}
  • 接口实现类 由原来的Impl实现类转换为一个Mapper配置文件
复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace绑定了一个对应的Dao/Mapper接口-->
<mapper namespace="com.hwt.dao.UserDao">
<!--    select查询-->
    <select id="getUserList" resultType="com.hwt.pojo.User">
        select * from mybatis.user
    </select>
</mapper>
复制代码

(四)测试

常见报错:

  1. 绑定异常:
 org.apache.ibatis.binding.BindingException: Type interface com.hwt.dao.UserDao is not known to the MapperRegistry.

解决方法:

mybatis配置文件添加
<!--    每一个Mapper.xml都需要在MyBatis核心配置文件中注册-->
 <mappers>
     <mapper resource="com/hwt/dao/UserMapper.xml"/>
 </mappers>
  1. 初始化异常
java.lang.ExceptionInInitializerError
    at com.hwt.dao.UserDaoTest.test(UserDaoTest.java:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

​ 解决方法:

复制代码
pom文件添加: 
<!--在build中配置resources,来防止资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>false</filtering>
            </resource>

            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
复制代码

MapperRegistry是什么?

核心配置文件中注册Mappers

  • junit测试
复制代码
public class UserDaoTest {
    @Test
    public void test(){
        //第一步,获取SqlSession对象
        SqlSession sqlSession = MybatisUntils.getSqlSession();
        // 执行sql
        //方式一:getMapper
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> userList = userDao.getUserList();

        for (User user : userList) {
            System.out.println(user);
        }
        //关闭sqlSession
        sqlSession.close();
    }
}
复制代码

排错思路:

  1. mybatis配置文件没有注册
  2. 绑定接口错误
  3. 方法名错误
  4. 返回类型错误
  5. maven导出资源更新

SqlSession

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

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

绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。

如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:

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

三、Mybatis下的增删改

(一)namespace

​ namespace中的包名需要和Dao/mapper接口的包名一致!

(二)select

​ ==选择、查询语句==

  • ​ id:对应的接口中的方法名
  • ​ resultType: sql语句执行的返回值类型
  • ​ parameterType:参数类型

1.编写接口

    //根据ID查询用户
    User getUserById(int id);

2.编写mapper文件中的sql语句

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

3.编写测试类

    @Test
    public void getUserById(){
        SqlSession sqlSession = MybatisUntils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(1);
        System.out.println(user);
        sqlSession.close();
    }

(三)insert

<insert id="addUser" parameterType="com.hwt.pojo.User">
    insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>

(四)update

<update id="updateUser" parameterType="com.hwt.pojo.User">
    update mybatis.user set name=#{name} ,pwd=#{pwd} where id=#{id};
</update>

(五)delete

<delete id="deleterUser" parameterType="int">
    delete from mybatis.user where id=#{id};
</delete>

(六)分析错误

  1. 标签匹配错误
  2. resource绑定mapper,MyBatis核心配置文件中注册需要使用路径(不能使用 点)
  3. NuLLPointerException,没有找到注册资源

(七)Map

如果实体类,或者数据库中的表,字段或者参数过多,使用Map

//插入用户
int addUser2(Map<String,Object> map);
<insert id="addUser2" parameterType="map">
    insert into mybatis.user (id,name,pwd) values (#{userid},#{username},#{password});
</insert>
复制代码
public void addUser2(){
    SqlSession sqlSession = MybatisUntils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    HashMap<String, Object> map = new HashMap<>();
    map.put("userid",5);
    map.put("username","hello");
    map.put("password","2222222");
    mapper.addUser2(map);
    sqlSession.commit();
    sqlSession.close();
}
复制代码
  • Map传递参数,直接在sql中取出key
  • 对象传递参数,直接在SQL中去除对象的属性
  • 一个参数,直接在sql中取到;多个参数时使用set

(八)模糊查询注意

mybatis中的#{value}${value}的区别:

  1. #{value}将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
  2. ${value}将传入的数据直接显示生成在sql中。
  3. #{value}方式能够很大程度防止sql注入。 
  4. ${value}方式无法防止Sql注入。
  5. ${value}方式一般用于传入数据库对象,例如传入表名.
  6. 一般能用#{value}的就别用value,mybatis排序时使用orderby动态参数时需要注意用{value}而不是#{value} 字符串替换。默认情况下,使用#{value}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值。这样做很安全,很迅速也是首选做法,有时你只是想直接在SQL语句中插入一个不改变的字符串。

==重要:==接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。

 

posted @   ImreW  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示