Mybatis框架(3) —— 使用代理持久层实现类实现CRUD操作

简介

  • MyBatis环境搭建 的方式在前面已经详细的介绍过了,本文将通过映射配置文件,使用代理持久层实现类的方式,来进行MySQL数据库的CRUD操作。
  • 环境搭建成功后,MySQL数据库的CRUD操作基于以下几个文件的基础上进行修改:
    • UserDao.java(持久层接口)
      • 添加CRUD操作的抽象方法。
    • UserDao.xml(持久层接口的映射配置文件)
      • 添加持久层接口的全类名:namespace
      • 添加CRUD操作的mapper子标签:select、update、insert、
      • 添加方法名:id
      • 添加返回值类型的全类名:resultType

环境搭建

Maven项目依赖

  • 在pom.xml 文件中,并不引入MyBatis框架的依赖:
    • mybatis(MyBatis框架)
    • mysql-connector-java(数据库连接)
    • junit (单元测试)
<?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>cn.water</groupId>
    <artifactId>section03_CRUD_ProxyDao</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- MyBatis框架 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!-- MySQL 数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!-- 单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>

</project>

数据库表

#创建数据库
CREATE DATABASE mybatis;
USE mybatis;

#创建表
CREATE TABLE USER(
	id INT(11) PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(32) NOT NULL COMMENT '用户名称',
	birthday DATETIME DEFAULT NULL COMMENT '生日',
	sex CHAR(1) DEFAULT NULL COMMENT '性别',
	address VARCHAR(256) DEFAULT NULL COMMENT '地址'	
) ENGINE = INNODB DEFAULT CHARSET = utf8;

#插入数据
INSERT INTO USER VALUES 
	(41,'老王','2018-02-27 17:47:08','男','北京'),
    (42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),
    (43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),
    (45,'传智播客','2018-03-04 12:04:06','男','北京金燕龙'),
    (46,'老王','2018-03-07 17:37:26','男','北京'),
    (48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');

目录结构

  • src/main
    • java
      • cn/water/dao
        • UserDao.java(持久层接口)
      • cn/water/domain
        • User.java(实体层)
      • resources
        • cn/water/dao
          • UserDao.xml(映射配置文件)
      • SqlMapConfig.xml(MyBatis主配置文件)
  • src/tese
    • java
      • cn/water/test
        • MybatisTest.java(测试文件)

实体类

User.java

package cn.water.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {

    /** 成员变量 */
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    /** 构造方法 */
    public User() {

    }

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


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

    /** Getter Setter */
    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    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;
    }


}

持久层接口

UserDao.java

package cn.water.dao;

import cn.water.domain.User;

import java.util.List;

public interface UserDao {

    /** 添加用户 */
    void add(User user);

    /** 更新用户 */
    void update(User user);

    /** 删除用户 */
    void delete(Integer id);

    /** 查询所有用户 */
    List<User> findAll();

    /** 查询单个用户 */
    User findOne(Integer id);

    /** 根据姓名模糊查询 */
    List<User> findByName(String name);

    /** 查询所有用户的数量 */
    Integer findTotal();


}

映射配置文件

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="cn.water.dao.UserDao">

            <!-- 添加用户 -->
                <!-- 参数类型 JavaBean,占位符 = 成员变量名的小写形式 -->
            <select id="add" parameterType="cn.water.domain.User" >
                INSERT INTO user VALUES ( #{id}, #{username}, #{birthday}, #{sex}, #{address} ) ;
            </select>

            <!-- 更新用户 -->
            <select id="update" parameterType="cn.water.domain.User">
                UPDATE user SET
                    username = #{username},
                    birthday = #{birthday},
                    sex = #{sex},
                    address = #{address}
                WHERE
                    id = #{id} ;
            </select>

            <!-- 删除用户 -->
                <!-- 参数类型 基本类型,占位符 = 方法参数名称 -->
            <select id="delete" parameterType="INT" >
                DELETE FROM user WHERE id = #{id};
            </select>

            <!-- 查询所有 -->
            <select id="findAll" resultType="cn.water.domain.User">
                SELECT * FROM user;
            </select>

            <!-- 查询单个用户 -->
            <select id="findOne" parameterType="INT" resultType="cn.water.domain.User">
                SELECT * FROM user WHERE id = #{id} ;
            </select>

            <!-- 根据姓名模糊查询 -->
            <select id="findByName" parameterType="java.lang.String" resultType="cn.water.domain.User">
                SELECT * FROM user WHERE username LIKE #{name};
            </select>
            <select id="findByName" parameterType="java.lang.String" resultType="cn.water.domain.User">
                SELECT * FROM user WHERE username LIKE '% {value} %';
            </select>

            <!-- 查询所有用户的数量 -->
            <select id="findTotal" resultType="INT" >
                SELECT COUNT(*) FROM user;
            </select>
        </mapper>

测试类

Test.java

package cn.water.test;

import cn.water.dao.UserDao;
import cn.water.domain.QueryVo;
import cn.water.domain.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.After;
import org.junit.Before;
import org.junit.Test;

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

public class UserTest {

    /* 成员变量 */
    private InputStream inputStream;
    private SqlSession session;
    private UserDao dao;

    /* 初始化操作 */
    @Before
    public void init() throws IOException {
        /* 加载 MyBatis配置文件 */
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        /* 获取 工厂类 */
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        /* 获取 产品类 */
        session = factory.openSession();
        /* 获取 代理对象 */
        dao = session.getMapper(UserDao.class);
    }

    /* 销毁操作 */
    @After
    public void destroy() throws IOException {
        session.close();
        inputStream.close();
    }


    /** 添加用户 */
    @Test
    public void test01(){
        dao.add( new User(100,"ADD",new Date(),"男","UserDao") );
        session.commit();
    }

    /** 更新用户 */
    @Test
    public void test02(){
        dao.update( new User(100,"UPDATE",new Date(),"男","UserDao") );
        session.commit();
    }

    /** 删除用户 */
    @Test
    public void test03(){
        dao.delete(100);
        session.commit();
    }

    /** 查询所有用户 */
    @Test
    public void test04(){
        for (User user : dao.findAll()) {
            System.out.println(user);
        }
    }

    /** 查询单个用户 */
    @Test
    public void test05(){
        System.out.println( dao.findOne(41) );
    }


    /** 根据用户模糊查询 */
    @Test
    public void test06(){
        // LIKE #{username} 使用的是PreparedStatement对象
        List<User> userList1 = dao.findByName01("%王%");
        // LIKE '%${value}%' 使用的是Statement对象
        List<User> userList2 = dao.findByName02("王");
        /* 输出 */
        for (User user : userList1) {
            System.out.println("1--"+user);
        }
        for (User user : userList2) {
            System.out.println("2--"+user);
        }
    }

    /** 查询所有用户的数量 */
    @Test
    public void test07(){
        System.out.println( dao.findTotal() );
    }

    /** 添加用户 + 返回ID */
    @Test
    public void test08(){
        System.out.println(dao.addReturnID(new User(100, "ADD RETURN", new Date(), "男", "UserDao")));
    }

    /** 根据QueryVo对象的条件,模糊查询 */
    @Test
    public void test09(){

        for(User user : dao.findByQueryVO(new QueryVo(new User(100, "ADD RETURN", new Date(), "男", "UserDao")))){
            System.out.println(user);
        }
    }


}

实现CRUD操作

  • 在前一篇博客里,我们学习了自定义MyBatis框架,当时我们使用了 Proxy类 和 MapperProxy类 实现了动态代理,并调用了 selectList方法 帮我去执行具体的SQL语句。尽管这并不是完全具体的MyBatis框架底层运作方式,但以目前的知识来讲就足够了。
  • 所以当我们使用代理持久层实现类的方式时,代理对象会帮我去调用 selectList方法;但是当我们使用手动编写持久层实现类的方式时,我们就需要自己去调用 selectList方法了。但关于这方面的事情,我不准备在下面讲,这是下一篇博客的事情了。
  • 本篇博客在实现CRUD操作的章节,主要用于描述 持久层接口和映射配置文件

思维导图

在这里插入图片描述

添加用户

  • 持久层接口
    void add(User user);
  • 映射配置文件
<select id="add" parameterType="cn.water.domain.User" >
    INSERT INTO user VALUES ( #{id}, #{username}, #{birthday}, #{sex}, #{address} ) ;
</select>

更新用户

  • 持久层接口
    void update(User user);
  • 映射配置文件
<select id="update" parameterType="cn.water.domain.User">
    UPDATE user SET
        username = #{username},
        birthday = #{birthday},
        sex = #{sex},
        address = #{address}
    WHERE
    	id = #{id} ;
</select>

删除用户

  • 持久层接口
    void delete(Integer id);
  • 映射配置文件
<select id="delete" parameterType="INT" >
    DELETE FROM user WHERE id = #{id};
</select>

查找所有用户

  • 持久层接口
    User findOne(Integer id);
  • 映射配置文件
<select id="findAll" resultType="cn.water.domain.User">
    SELECT * FROM user;
</select>

查询单个用户

  • 持久层接口
    List<User> findAll();
  • 映射配置文件
 <select id="findOne" parameterType="INT" resultType="cn.water.domain.User">
     SELECT * FROM user WHERE id = #{id} ;
</select>

根据姓名模糊查询

  • 持久层接口
    List<User> findByName01(String name);
    List<User> findByName02(String name);
  • 映射配置文件
<select id="findByName01" parameterType="java.lang.String" resultType="cn.water.domain.User">
    SELECT * FROM user WHERE username LIKE #{username};
</select>

<select id="findByName02" parameterType="java.lang.String" resultType="cn.water.domain.User">
    SELECT * FROM user WHERE username LIKE '%${value}%';
</select>

查询所有用户数量

  • 持久层接口
    Integer findTotal();
  • 映射配置文件
<select id="findTotal" resultType="INT" >
    SELECT COUNT(*) FROM user;
</select>

添加用户返回ID

  • 持久层接口
<insert id="addReturnID" parameterType="cn.water.domain.User">
	<selectKey keyProperty="id" keyColumn="id" resultType="INT" order="AFTER">
    	SELECT last_insert_id();
    </selectKey>
    INSERT INTO
        usr
    VALUES
        (null,#{username},#{birthday},#{sex},#{address});
</insert>
  • 映射配置文件
for(User user : dao.findByQueryVO(new QueryVo(new User(100, "ADD RETURN", new Date(), "男", "UserDao")))){
	System.out.println(user);
}

【OGNL表达式】

  • Object Graphic Navigation Language:对象图导航语言
    • 获取数据的一种表达式,在形式上省略了get
      • Java表达式:user.getUsername();
      • OGNL表达式:user.username
      • MyBatis表达式:username
  • 其实在MyBatis的映射配置文件中,我们使用的也是OGNL表达式。只是由于我们再 parameterType属性中已经提供了实体类,所以我们可以省略实体类名直接使用属性名来获取数据。

【POJO对象】

  • POJO对象等同于JavaBean对象,属于实体类的一种。
  • 我们通过User对象来传递查询条件时,查询条件的范围有限,只能是User对象中有的数据。但在实际操作中,除了需要User对象的查询条件,还会需要其他对象的查询条件,此时使用User对象来传递查询条件显然是不够的。
  • 通过POJO对象来传递查询条件的优势正在于此,将User对象以及所需的其他对象作为成员变量封装进POJO对象,在查询时,就可以使用多个对象的查询条件。

根据Query对象的条件,模糊查询

  • QueryVo对象
    • 将User对象封装进QueryVo对象中,并通过QueryVo对象来获取User对象中Username的值,用于进行模糊查询。
package cn.water.domain;

public class QueryVo {

    /* 成员变量 */
    private User user;

    /* 构造方法 */
    public QueryVo(User user) {
        this.user = user;
    }

    /* Getter Setter */
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

  • 持久层接口
    List<User> findByQueryVO(QueryVo queryVo);
  • 映射配置文件
<select id="findByQueryVo" parameterType="cn.water.domain.QueryVo" resultType="cn.water.domain.User">
    SELECT * FROM user WHERE username LIKE #{user.username};
</select>

执行过程(思维导图)

在这里插入图片描述

发布了68 篇原创文章 · 获赞 2 · 访问量 1921

猜你喜欢

转载自blog.csdn.net/qq_40981851/article/details/104191858