三、MyBatis 使用传统 Dao 开发方式

1.0 使用 Dao 的实现类,操作数据库

1.0.1 Dao 开发

(0)定义接口StudentDao 及创建接口的映射文件StudentDao .xm
package com.zep.dao;

import com.zep.domain.Student;

import java.util.List;

public interface StudentDao {
    
    

    List<Student> selectStudents();

    int insertStudent(Student student);

    int updateStudent(Student student);

    int deleteStudent(int id);
}

<?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.zep.dao.StudentDao">
    <select id="selectStudents" resultType="com.zep.domain.Student">
        select * from student order by id;
    </select>

    <insert id="insertStudent">
        insert into student values(#{
    
    id},#{
    
    name},#{
    
    email},#{
    
    age})
    </insert>

    <update id="updateStudent">
         update student set age = #{
    
    age} where id=#{
    
    id}
    </update>

    <delete id="deleteStudent">
        delete from student where id=#{
    
    studentId}
    </delete>
</mapper>
(1) 创建 Dao 接口实现类

public class StudentDaoImpl implements StudentDao

(2) 实现接口中 select 方法
@Override
    public List<Student> selectStudents() {
    
    
        // 1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        String sqlId = "com.zep.dao.StudentDao.selectStudents";
        // 2.执行sql语句,使用SqlSession类的方法
        List<Student> students = sqlSession.selectList(sqlId);
        /*for (Student student : students) {
            System.out.println(student);
        }*/
        // 3.关闭
        sqlSession.close();
        return students;
    }

测试查询操作:
MyBatisTest 类中创建 StudentDaoImpl 对象

public class TestMybatis {
    
    
    @Test
    public void testSelectStudents() {
    
    
        StudentDaoImpl dao = new StudentDaoImpl();
        List<Student> students = dao.selectStudents();
        for (Student student : students) {
    
    
            System.out.println(student);
        }
    }
}

(3) 实现接口中 insert 方法

    @Override
    public int insertStudent(Student student) {
    
    
        // 1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        String sqlId = "com.zep.dao.StudentDao.insertStudent";
        // 2.执行sql语句,使用SqlSession类的方法
        int nums = sqlSession.insert(sqlId,student);
        // 3.提交事务
        sqlSession.commit();
        // 4.关闭
        sqlSession.close();
        return nums;
    }

测试 insert

@Test
    public void testInsertStudent() {
    
    
        StudentDaoImpl dao = new StudentDaoImpl();
        Student student = new Student();
        student.setId(1003);
        student.setName("zep");
        student.setEmail("[email protected]");
        student.setAge(22);
        int nums = dao.insertStudent(student);
        System.out.println("添加对象的数量:" + nums);
    }

(4) 实现接口中 update 方法

 @Override
public int updateStudent(Student student) {
    
    
        SqlSession session = MybatisUtils.getSqlSession();
        int nums = session.update(
                "com.zep.dao.StudentDao.updateStudent",student);
        session.commit();
        session.close();
        return nums;
    }

测试 update

@Test
public void testUpdateStudent() {
    
    
        StudentDaoImpl dao = new StudentDaoImpl();
        Student student = new Student();
        student.setId(1004);
        student.setAge(222);
        int nums = dao.updateStudent(student);
        System.out.println("使用Dao修改数据:" + nums);
    }

(5) 实现接口中 delete 方法

@Override
public int deleteStudent(int id) {
    
    
        SqlSession session = MybatisUtils.getSqlSession();
        int nums = session.delete(
                "com.zep.dao.StudentDao.deleteStudent",id);
        session.commit();
        session.close();
        return nums;
    }

测试 delete

 @Test
    public void testDeleteStudent() {
    
    
        StudentDaoImpl dao = new StudentDaoImpl();
        int nums = dao.deleteStudent(1005);
        System.out.println("使用Dao删除的数据:" + nums);
    }

项目完整代码如下:
在这里插入图片描述
pom.xml:

<?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>com.zep</groupId>
  <artifactId>ch02-mybatis-dao</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <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.1</version>
    </dependency>

    <!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>

  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>


Student .java:

package com.zep.domain;
// 推荐和表名一样,容易记忆
public class Student {
    
    
    // 定义属性,目前要求是 属性名和列名保持一致
    private Integer id;
    private String name;
    private String email;
    private Integer age;

    public Integer getId() {
    
    
        return id;
    }

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

    public String getName() {
    
    
        return name;
    }

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

    public String getEmail() {
    
    
        return email;
    }

    public void setEmail(String email) {
    
    
        this.email = email;
    }

    public Integer getAge() {
    
    
        return age;
    }

    public void setAge(Integer age) {
    
    
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}

mybatis.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>
    <!--mybatis.xml 文件加入日志配置,可以在控制台输出执行的 sql 语句和参数-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/zep/dao/StudentDao.xml"/>
    </mappers>
</configuration>


MybatisUtils .java:

package com.zep.utils;

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 java.io.IOException;
import java.io.InputStream;


public class MybatisUtils {
    
    

    private static SqlSessionFactory factory = null;

    /*静态代码块:执行优先级高于非静态的初始化块,它会在类初始化的时候执行一次,执行完成便销毁*/
    //使用 静态块 创建一次 SqlSessionFactory
    static {
    
    
        String config = "mybatis.xml"; //需要和你的项目中的文件名一样
        try {
    
    
            //读取配置文件
            InputStream in = Resources.getResourceAsStream(config);
            //创建SqlSessionFactory对象,使用SqlSessionFactoryBuilder
            factory = new SqlSessionFactoryBuilder().build(in);

        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

    // 获取SqlSession对象的方法
    public static SqlSession getSqlSession() {
    
    
        SqlSession sqlSession = null;
        if (factory != null) {
    
    
            sqlSession = factory.openSession(); // 非自动提交事务
        }
        return sqlSession;
    }
}

StudentDao .java:

package com.zep.dao;

import com.zep.domain.Student;

import java.util.List;

public interface StudentDao {
    
    

    List<Student> selectStudents();

    int insertStudent(Student student);

    int updateStudent(Student student);

    int deleteStudent(int id);
}

StudentDao.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.zep.dao.StudentDao">
    <select id="selectStudents" resultType="com.zep.domain.Student">
        select * from student order by id;
    </select>

    <insert id="insertStudent">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>

    <update id="updateStudent">
         update student set age = #{age} where id=#{id}
    </update>

    <delete id="deleteStudent">
        delete from student where id=#{studentId}
    </delete>
</mapper>

StudentDaoImpl .java:

package com.zep.dao.Impl;

import com.zep.dao.StudentDao;
import com.zep.domain.Student;
import com.zep.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class StudentDaoImpl implements StudentDao {
    
    
    @Override
    public List<Student> selectStudents() {
    
    
        // 1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        String sqlId = "com.zep.dao.StudentDao.selectStudents";
        // 2.执行sql语句,使用SqlSession类的方法
        List<Student> students = sqlSession.selectList(sqlId);
        /*for (Student student : students) {
            System.out.println(student);
        }*/
        // 3.关闭
        sqlSession.close();
        return students;
    }

    @Override
    public int insertStudent(Student student) {
    
    
        // 1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        String sqlId = "com.zep.dao.StudentDao.insertStudent";
        // 2.执行sql语句,使用SqlSession类的方法
        int nums = sqlSession.insert(sqlId,student);
        // 3.提交事务
        sqlSession.commit();
        // 4.关闭
        sqlSession.close();
        return nums;
    }

    public int updateStudent(Student student) {
    
    
        SqlSession session = MybatisUtils.getSqlSession();
        int nums = session.update(
                "com.zep.dao.StudentDao.updateStudent",student);
        session.commit();
        session.close();
        return nums;
    }
    @Override
    public int deleteStudent(int id) {
    
    
        SqlSession session = MybatisUtils.getSqlSession();
        int nums = session.delete(
                "com.zep.dao.StudentDao.deleteStudent",id);
        session.commit();
        session.close();
        return nums;
    }
}

TestMybatis .java:

package com.zep;

import com.zep.dao.Impl.StudentDaoImpl;
import com.zep.domain.Student;
import org.junit.Test;

import java.util.List;

public class TestMybatis {
    
    

    @Test
    public void testSelectStudents() {
    
    
        //com.zep.dao.StudentDao
        StudentDaoImpl dao = new StudentDaoImpl();

        /**
         * 调用List<Student> students = dao.selectStudents();
         *  1.dao对象,类型是StudentDao,可以获取到它的全限定类名为:com.zep.dao.StudentDao
         *  这个全限定名称和StudentDao.xml文件中mapper的namespace的值是一样的
         *
         *  2.方法名称,selectStudents,这个方法就是StudentDao.xml文件中mapper标签下的子标签中id的值selectStudents
         *
         *  3.通过dao中方法的返回值也可以确定Mybatis要调用的SqlSession的方法
         *      如果返回值是List,调用的是SqlSession.selectList()方法。
         *      如果返回值是int,或者是非List的,看mapper文件中的标签是<insert>,<update>
         *          就会调用SqlSession的insert(),update()等方法
         *
         *  mybatis的动态代理:mybatis根据dao的方法调用,获取执行sql语句的信息。
         *      mybatis根据你的dao接口,创建出一个dao接口的实现类,并创建这个类的对象来完成
         *      SqlSession调用方法,访问数据库。
         */
        List<Student> students = dao.selectStudents();
        for (Student student : students) {
    
    
            System.out.println(student);
        }
    }


    @Test
    public void testInsertStudent() {
    
    
        StudentDaoImpl dao = new StudentDaoImpl();
        Student student = new Student();
        student.setId(1005);
        student.setName("zep");
        student.setEmail("[email protected]");
        student.setAge(22);
        int nums = dao.insertStudent(student);
        System.out.println("添加对象的数量:" + nums);
    }

    @Test
    public void testUpdateStudent() {
    
    
        StudentDaoImpl dao = new StudentDaoImpl();
        Student student = new Student();
        student.setId(1004);
        student.setAge(222);
        int nums = dao.updateStudent(student);
        System.out.println("使用Dao修改数据:" + nums);
    }

    @Test
    public void testDeleteStudent() {
    
    
        StudentDaoImpl dao = new StudentDaoImpl();
        int nums = dao.deleteStudent(1005);
        System.out.println("使用Dao删除的数据:" + nums);
    }

}

在这里插入图片描述

1.0.2 传统 Dao 开发方式的分析

在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么实质性的工作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper (StudentDao.xml)中相应 id 的 SQL 语句,真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。

所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对DB 进行操作。这种对 Dao 的实现方式称为 Mapper 的动态代理方式。

Mapper 动态代理方式无需程序员实现 Dao 接口,不需要我们自己编写Dao接口的实现类。接口是由 MyBatis 结合映射文件自动生成的动态代理实现的

猜你喜欢

转载自blog.csdn.net/weixin_44827418/article/details/111408608