MyBatis框架总结SSM框架1

本文主要介绍了SSM框架中的MyBatis,包括快速入门和进阶内容。在快速入门部分,讲述了如何使用MyBatis查询用户并封装到List集合。进阶部分涉及用户增加、删除和模糊查询的操作,强调了MyBatis在处理主键返回值和事务提交上的处理方式。此外,还展示了如何在测试类中执行这些操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SSM框架

web层      springMVC

业务层     spring

 持久层    MyBatis

jdbc 程序回顾

  • 注册驱动

  • 获得连接

  • 创建预编译sql语句对象

  • 设置参数, 执行

  • 处理结果

  • 释放资源

  •     public static void main(String[] args) {
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            try {
                //1.加载数据库驱动
                Class.forName("com.mysql.jdbc.Driver");
                //2.通过驱动管理类获取数据库链接
                connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "123456"); 
                //3.定义 sql 语句 ?表示占位符
                String sql = "select name from user where username = ?";
                //4.获取预处理 statement
                preparedStatement = connection.prepareStatement(sql);
                //5.设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值
                preparedStatement.setString(1, "王五");
                //6.向数据库发出 sql 执行查询,查询出结果集
                resultSet = preparedStatement.executeQuery();
                //7.遍历查询结果集
                while (resultSet.next()) {
                    System.out.println(resultSet.getString("id") + "
                            "+resultSet.getString(" username"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
    		//8.释放资源
                if (resultSet != null) {
                    try {
                        resultSet.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if (preparedStatement != null) {
                    try {
                        preparedStatement.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    jdbc 问题分析

  • 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

  • Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大, sql 变动需要改变java 代码。

  • 使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。

  • 对结果集解析存在硬编码(查询列名), sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成 pojo 对象解析比较方便

  • MyBatis: 持久层的一个框架, 封装了JDBC. 操作数据库

  • 为什么要学习MyBatis?

    • JDBC那一套代码和DBUtils都有一些很明显的缺点, JDBC和DBUtils不适合做项目

    • MyBatis是工作里面的主流的持久层框架, 使用几率特别大

Mybatis快速入门

1.需求

  • 使用MyBatis查询所有的用户, 封装到List集合

2.分析

  1. 创建Maven工程(java), 添加mybatis的依赖坐标

  2. 创建pojo (javabean)

  3. 创建UserDao接口

  4. 创建UserDao映射文件 (xml配置文件)

  5. 创建MyBatis核心配置文件SqlMapConfig.xml (xml配置文件)

  6. 编写java代码测试

  7. CREATE DATABASE mybatis_day01;
    USE mybatis_day01;
    CREATE TABLE t_user(
    		uid int PRIMARY KEY auto_increment,
    		username varchar(40),
    	 	sex varchar(10),
    		birthday date,
    		address varchar(40)
    );
    
    INSERT INTO `t_user` VALUES (null, 'zs', '男', '2018-08-08', '北京');
    INSERT INTO `t_user` VALUES (null, 'ls', '女', '2018-08-30', '武汉');
    INSERT INTO `t_user` VALUES (null, 'ww', '男', '2018-08-08', '北京');

    创建Maven工程(jar)导入坐标

     <!--1. 添加依赖-->
        <dependencies>
            <!--MyBatis坐标-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.6</version>
            </dependency>
            <!--mysql驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.37</version>
            </dependency>
            <!--单元测试-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
    
            <!--lombok 依赖-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.18</version>
            </dependency>
        </dependencies>

    创建User实体类

package com.itheima.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int uid;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
}

创建 UserDao 接口

package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {

    /**
     * 查询所有
     * @return
     */
    List<User> findAll();
}

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

<!--
    这个文件其实就是我们dao的映射文件,通俗的讲,就是当我们要调用UserDao里面的findAll方法的时候
        要执行什么样的sql语句,要在这里做配置!

    1. 有接口,就有映射文件
    2. 映射文件是一个xml文件,要放在resource文件夹里面,需要为它创建一个目录
    3. 记住一下套路:
        a. xml的目录最好要和dao接口的包名路径一样!
        b. xml的目录创建的时候必须要使用 / 的形式,不能使用 . 的形式创建!
        c. xml里面的命名空间必须要写成dao接口的全路径!
        d. xml里面的语句的id值必须是dao接口的方法名字!
        e. resultType: 写的是方法的返回值类型,如果方法的返回值是集合类型,那么写的是集合中的元素类型。
        f. parameterType : 写的是参数的类型,参数是什么类型,就写什么类型,即是是集合,也写的是集合的类型。

-->
<mapper namespace="com.itheima.dao.UserDao">
    <!--在这里写方法对应的sql语句-->
    <select id="findAll"  resultType="com.itheima.bean.User">
        select * from t_user
    </select>
    
</mapper>

创建 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">

<!--
这个文件是mybatis的核心配置文件,它里面包含两部分内容: 连接数据库, 映射文件在哪里-->

<configuration>

    <!--
        1. 数据库的连接
            environments : 用于配置环境,它里面可以定义多个环境,使用  environment来定义
                到底是用哪一个环境,取决于 default属性写的是哪个  environment的id值
               environment : 用于定义环境,
                    id :声明一个标识,唯一标识
                transactionManager : 事务管理员
                dataSource :用不用连接池
    -->
    <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/mybatis_day01"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--2. 映射文件在哪里?-->
    <mappers>
        <mapper resource="com/itheima/dao/UserDao.xml"/>
    </mappers>

</configuration>

package com.itheima.test;

import com.itheima.bean.User;
import com.itheima.dao.UserDao;
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.IOException;
import java.io.InputStream;
import java.util.List;

public class TestUserDao {

    //查询所有
    @Test
    public void testFindAll() throws IOException {

        //1. 读取SQLMapConfig文件,读取成一个输入流
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

        //2. 构建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

        //3. 使用输入流来构建SqlSessionFactory
        SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(is);

        //4. 问SqlSessionFactory要SqlSession
        SqlSession session = sessionFactory.openSession();

        //5. 问SqlSession要UserDao的代理对象
        UserDao dao = session.getMapper(UserDao.class);

        //6. 有了代理对象,就可以调用findAll方法
        List<User> list = dao.findAll();
        System.out.println("list = " + list);

        //7. 关闭SqlSession
        session.close();
    }
}
掌握Mapper动态代理方式规范

MyBatis进阶【重点】

package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {

    /**
     * 添加
     * @param user
     * @return 影响的行数
     */
    int add(User user);
}

<?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.itheima.dao.UserDao">


    <!--添加用户: 增删改操作不用写返回的类型,mybatis会自动返回影响的行数-->
    <insert id="add" parameterType="com.itheima.bean.User">
        insert into t_user values(null , #{username} , #{sex} ,#{birthday} , #{address})
    </insert>
</mapper>

package com.itheima.test;

import com.itheima.bean.User;
import com.itheima.dao.UserDao;
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.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class TestUserDao {

    @Test
    public void testAdd() throws IOException {

        //1. 读取SqlMapConfig文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

        //2. 构建SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

        //3. 构建SqlSessionFactory
        SqlSessionFactory factory = builder.build(is);

        //4. 构建SqlSession
        SqlSession session = factory.openSession();

        //5. 问SqlSession要dao的代理
        UserDao userDao = session.getMapper(UserDao.class);

        //6. 调用方法
        User user = new User();
        user.setUsername("zhangsan");
        user.setSex("男");
        user.setBirthday(new Date());
        user.setAddress("深圳");
        userDao.add(user);

        //7. 提交事务: mybatis没有默认提交事务 ,它把setAutoCommit(false), 所以对于增删改操作,要记得提交事务
        session.commit();

        //8. 关闭SqlSession
        session.close();
    }
}

新增用户 id 的返回值

  1. 有时候我们存在一些场景,把一条数据存储到数据库了之后,需要马上得到这条记录的id值。因为这条数据是我们自己创建赶出来的,它的id是多少,我们是不知道的,只有这条记录已经存在于数据库里面了,才知道它的id值。

  2. 什么情况下|场景下,我们需要在插入完这条记录之后,立即就需要得到这条记录的id呢?

    当我们往A表里面添加一条记录之后,需要继续往B表里面添加一条记录,但是A表和B表形成了一种主外键关系。B表里面的外键就是A表里面的主键,所以往B表里面添加记录,必须要先知道A表的这条记录的主键

新增用户后, 同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长 auto_increment 的值返回。

UserDao.xml

package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {
    /**
     * 添加: 获取主键id,使用selectKey去获取
     * @param user
     * @return
     */
    int add02(User user);
}

 UserDao.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.itheima.dao.UserDao">


    <!--添加用户:并且获取id主键返回-->
    <insert id="add02" parameterType="com.itheima.bean.User">
         insert into t_user values(null , #{username} , #{sex} ,#{birthday} , #{address})

         <!--
            获取主键 alt + shift + 方向上下 移动快捷键
                selectKey: 主要使用来获取主键id
                    keyProperty : 用参数user里面的什么属性来接收主键值
                    resultType:  接收主键的属性是什么类型
                    order: 只能写两个值: before | after
                        BEFORE:  先执行获取id的操作,再去执行添加数据的操作
                        AFTER : 先执行添加的操作,再去执行获取id的操作。

                        SELECT LAST_INSERT_ID() : 获取id的语句
         -->
         <selectKey keyProperty="uid" resultType="int" order="AFTER">
                SELECT LAST_INSERT_ID()
         </selectKey>
    </insert>
</mapper>

  • 方式二:属性配置

    在isnert标签里面直接使用属性keyProperty 和 useGeneratedKeys来设置获取主键id值。

UserDao.java

package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {
    /**
     * 添加: 获取主键id,使用属性的写法来获取
     * @param user
     * @return
     */
    int add03(User user);
}

 UserDao.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.itheima.dao.UserDao">

    <!--
        添加用户,获取id主键返回
            keyProperty :表示,使用参数user对象里面的什么属性来接收主键id
            useGeneratedKeys: 表示,是否使用数据库自增创建创建出来的主键id值,还是由mybatis自己搞出来的id值。
                true: 使用数据库创建给出来的id值
                false: 不是用数据库创建出来的id值,由mybatis给出来。
     -->
    <insert id="add03" parameterType="com.itheima.bean.User" keyProperty="uid" useGeneratedKeys="true">
        insert into t_user values(null , #{username} , #{sex} ,#{birthday} , #{address})
    </insert>
</mapper>

新增用户 id 的返回值(字符串类型)

主键不一定是int类型... 主键也可以是字符串类型。只有到以后做项目,有数据库合并,数据库集群的时候。

字符串类型的主键通常就是UUID生成的一串32个字符的字符串。 数据库合并!

package com.itheima.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String myId;
    private int uid;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
}

package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {

    /**
     * 添加: 获取主键id 使用selectKey标签来获取,主键是字符串类型。
     * @param user
     * @return
     */
    int add04(User user);
}

UserDao.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.itheima.dao.UserDao">


    <!--添加用户,获取id主键返回,但是主键是字符串类型的主键-->
    <insert id="add04" parameterType="com.itheima.bean.User" >
        insert into t_user values(null , #{username} , #{sex} ,#{birthday} , #{address})

        <selectKey keyProperty="myId" resultType="String" order="BEFORE">
            select uuid()
        </selectKey>
    </insert>
</mapper>

修改用户

  • UserDao中添加修改方法

package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {

    //=======================修改=======================

    /**
     * 根据id来查询用户
     * @param id
     * @return
     */
    User findById(int id);

    /**
     * 修改用户
     * @param user
     * @return
     */
    int update(User user);
}
 

<?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.itheima.dao.UserDao">

    <!--=========================更新===========================-->

    <!--根据id来查询用户-->
    <select id="findById" parameterType="int" resultType="com.itheima.bean.User">
        select * from t_user where uid = #{id}
    </select>

    <!--更新用户-->
    <update id="update" parameterType="com.itheima.bean.User">
        update t_user set username = #{username} , sex = #{sex} , birthday=#{birthday} , address= #{address} where uid = #{uid}
    </update>
</mapper>

//修改用户
    @Test
    public void testUpdate() throws IOException {

        //1. 读取SqlMapConfig文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

        //2. 构建SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

        //3. 构建SqlSessionFactory
        SqlSessionFactory factory = builder.build(is);

        //4. 构建SqlSession
        SqlSession session = factory.openSession();

        //5. 问SqlSession要dao的代理
        UserDao userDao = session.getMapper(UserDao.class);

        //6. 调用方法
        User user = userDao.findById(7);

        //修改数据
        user.setUsername("lisi");

        userDao.update(user);

        //7. 提交事务: mybatis没有默认提交事务 ,它把setAutoCommit(false), 所以对于增删改操作,要记得提交事务
        session.commit();

        //8. 关闭SqlSession
        session.close();
    }

        

删除用户

package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {

    /**
     * 删除用户
     * @param id
     * @return
     */
    int delete(int id);
}
  • 在 UserDao.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.itheima.dao.UserDao">

	<!--删除用户-->
    <delete id="delete" parameterType="int">
        delete from t_user where uid = #{id}
    </delete>

</mapper>

添加测试类中的测试方法


    //删除用户
    @Test
    public void testDelete() throws IOException {

        //1. 读取SqlMapConfig文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

        //2. 构建SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

        //3. 构建SqlSessionFactory
        SqlSessionFactory factory = builder.build(is);

        //4. 构建SqlSession
        SqlSession session = factory.openSession();

        //5. 问SqlSession要dao的代理
        UserDao userDao = session.getMapper(UserDao.class);

        //6. 调用方法
        userDao.delete(7);

        //7. 提交事务: mybatis没有默认提交事务 ,它把setAutoCommit(false), 所以对于增删改操作,要记得提交事务
        session.commit();

        //8. 关闭SqlSession
        session.close();
    }

模糊查询


package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {

	/**
     * 模糊查询,根据姓氏来查询用户
     * @param name
     * @return
     */
    List<User> findByUsername(String name);

}
<?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.itheima.dao.UserDao">

    <!--1. 从外面传递进来 % 的写法-->
    <select id="findByUsername" parameterType="string" resultType="com.itheima.bean.User">
        select * from t_user where username like #{name}
    </select>
</mapper>

//模糊查询: 从外面传递进去 %
    @Test
    public void testFindByUsername() throws IOException {

        //1. 读取SqlMapConfig文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

        //2. 构建SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

        //3. 构建SqlSessionFactory
        SqlSessionFactory factory = builder.build(is);

        //4. 构建SqlSession
        SqlSession session = factory.openSession();

        //5. 问SqlSession要dao的代理
        UserDao userDao = session.getMapper(UserDao.class);

        //6. 调用方法
        List<User> list = userDao.findByUsername("zhang%");
        System.out.println("list = " + list);

        //8. 关闭SqlSession
        session.close();
    }

package com.itheima.dao;

import com.itheima.bean.User;

import java.util.List;

public interface UserDao {

/**
     * 模糊查询,根据姓氏来查询用户
     * @param name
     * @return
     */
    List<User> findByUsername02(String name);

    /**
     * 模糊查询,根据姓氏来查询用户
     * @param name
     * @return
     */
    List<User> findByUsername03(String name);

    /**
     * 模糊查询,根据姓氏来查询用户
     * @param name
     * @return
     */
    List<User> findByUsername04(String name);
}
<?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.itheima.dao.UserDao">

    <!--2. 在语句里面追加 % , 外面不传递进来 % , 使用#{}取参数的值 -->
    <select id="findByUsername02" parameterType="string" resultType="com.itheima.bean.User">
        select * from t_user where username like #{name}"%"
    </select>

    <!--3. 在语句里面追加 % , 外面不传递进来 % , 使用${}取参数的值-->
    <select id="findByUsername03" parameterType="string" resultType="com.itheima.bean.User">
        select * from t_user where username like '${value}%'
    </select>

    <!--4. 在语句里面追加 % , 外面不传递进来 % , 使用#{}取参数的值-->
    <select id="findByUsername04" parameterType="string" resultType="com.itheima.bean.User">
        <!--select * from t_user where username like concat("%" , #{name} , "%")-->
        select * from t_user where username like concat( #{name} , "%")
    </select>

</mapper>

4.小结

  1. 传递简单类型

#{任意字段}或者${value}
  1. 传递pojo对象类型

#{javaBean属性名}或者${javaBean属性名}
  1. 传递的包装的pojo

#{属性名.属性名} 或者${属性名.属性名} 
  1. 传递多个参数

#{别名}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值