【Mybatis入門から実戦までのチュートリアル】 第2章 Mybatis DAO開発

2.Mybatis DAO開発

通常、Mybatis を使用した Dao の開発方法には、独自の Dao 開発方法と Mapper インターフェイス開発方法の 2 つの方法があります。

2.1 マイバティス API

2.1.1 SqlSessionFactoryBuilder

    SqlSessionFactoryBuilder は、SqlSessionFactoryBuilder を作成するために使用されます.SqlSessionFactoryBuilder が作成されると、SqlSessionFactoryBuilder は必要ありません.SqlSessionFactory を介して SqlSession が生成されるため、SqlSessionFactoryBuilder をツール クラスとして使用できます.最適な使用範囲は、メソッド スコープ、つまり、メソッド本体。

2.1.2 SqlSessionFactory

    SqlSessionFactory は、openSession のさまざまなオーバーロード メソッドを定義するインターフェースです。SqlSessionFactory の最適な使用法は、アプリケーション全体の実行中です。一度作成すると、再利用できます。SqlSessionFactory は通常、シングルトン モードで管理されます。

    注: openSession (true)、true はトランザクションを自動的にコミットする場合、false はその逆です。

2.1.3 SQL セッション

    SqlSession はユーザー指向 (プログラマ) のインターフェイスであり、データベースを操作するための多くのメソッドを提供します。例: selectOne (単一のオブジェクトを返す)、selectList (単一または複数のオブジェクトを返す)、挿入、更新、削除。

    SqlSession のインスタンスは共有できず、スレッド セーフではありません。各スレッドは SqlSession の独自のインスタンスを持つ必要があるため、最適なスコープはリクエストまたはメソッド スコープです。クラスの静的フィールドまたはインスタンス フィールドに SqlSession インスタンスへの参照を配置しないでください。

2.2 Mybatis ツールクラス

    MyBatis の開発を簡素化するために、MyBatis をさらにパッケージ化することができます。

package com.newcapec.util;

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;

/**
 * Mybatis工具类
 */
public class MybatisUtil {
    /**
     * 不让用户在外界创建工具类对象
     */
    private MybatisUtil() {
    }

    /**
     * 初始化SqlSessionFactory对象
     */
    private static SqlSessionFactory factory;

    static {
        try {
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取SqlSession对象的方法
     */
    public static SqlSession getSession() {
        return factory.openSession();
    }
}

テスト:

public class MybatisUtilTest {
    @Test
    public void test() {
        SqlSession sqlSession = MybatisUtil.getSession();
        System.out.println(sqlSession);
        sqlSession.close();
    }
}

2.3 独自のDAO開発手法

    オリジナルの Dao 開発方法では、Dao インターフェイスと Dao 実装クラスをプログラマーが作成する必要があり、Dao 実装クラスでマッピング ファイルに定義された sql を呼び出すだけです。

2.3.1 エンティティクラス

package com.newcapec.entity;

/**
 * Dept实体类
 */
public class Dept {

    private Integer deptno;
    private String dname;
    private String loc;

    public Integer getDeptno() {
        return deptno;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                ", loc='" + loc + '\'' +
                '}';
    }
}

2.3.2 インターフェース

package com.newcapec.dao;

import com.newcapec.entity.Dept;

import java.util.List;

public interface DeptDao {
    List<Dept> select();

    Dept selectById(Integer deptno);

    int insert(Dept dept);

    int update(Dept dept);

    int delete(Integer deptno);
}

2.3.3 実装クラス

package com.newcapec.dao.impl;

import com.newcapec.dao.DeptDao;
import com.newcapec.entity.Dept;
import com.newcapec.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

/**
 * DeptDao实现类
 */
public class DeptDaoImpl implements DeptDao {
    @Override
    public List<Dept> select() {
        SqlSession sqlSession = MybatisUtil.getSession();
        List<Dept> list = sqlSession.selectList("dept.select");
        sqlSession.close();
        return list;
    }

    @Override
    public Dept selectById(Integer deptno) {
        SqlSession sqlSession = MybatisUtil.getSession();
        Dept dept = sqlSession.selectOne("dept.selectById", deptno);
        sqlSession.close();
        return dept;
    }

    @Override
    public int insert(Dept dept) {
        SqlSession sqlSession = MybatisUtil.getSession();
        int result = sqlSession.insert("dept.insert", dept);
        sqlSession.commit();
        sqlSession.close();
        return result;
    }

    @Override
    public int update(Dept dept) {
        SqlSession sqlSession = MybatisUtil.getSession();
        int result = sqlSession.update("dept.update", dept);
        sqlSession.commit();
        sqlSession.close();
        return result;
    }

    @Override
    public int delete(Integer deptno) {
        SqlSession sqlSession = MybatisUtil.getSession();
        int result = sqlSession.delete("dept.delete", deptno);
        sqlSession.commit();
        sqlSession.close();
        return result;
    }
}

2.3.4 マッパーファイル

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

    <select id="select" resultType="com.newcapec.entity.Dept">
        select deptno,dname,loc from dept
    </select>

    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.Dept">
        select deptno,dname,loc from dept where deptno=#{deptno}
    </select>

    <insert id="insert" parameterType="com.newcapec.entity.Dept">
        insert into dept(dname,loc) values(#{dname},#{loc})
    </insert>

    <update id="update" parameterType="com.newcapec.entity.Dept">
        update dept set dname=#{dname},loc=#{loc} where deptno=#{deptno}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        delete from dept where deptno=#{deptno}
    </delete>
</mapper>

マッパー ファイルをロードします。

<!-- 加载映射文件的位置 -->
<mappers>
    <mapper resource="mapper/Dept.xml"/>
</mappers>

2.3.5 テスト

package com.newcapec;

import com.newcapec.dao.DeptDao;
import com.newcapec.dao.impl.DeptDaoImpl;
import com.newcapec.entity.Dept;
import org.junit.Test;

import java.util.List;

public class DaoTest {

    private DeptDao deptDao = new DeptDaoImpl();

    @Test
    public void testSelect() {
        List<Dept> list = deptDao.select();
        for (Dept dept : list) {
            System.out.println(dept);
        }
    }

    @Test
    public void testSelectById() {
        Dept dept = deptDao.selectById(20);
        System.out.println(dept);
    }

    @Test
    public void testInsert() {
        Dept dept = new Dept();
        dept.setDname("企划部");
        dept.setLoc("深圳");
        int result = deptDao.insert(dept);
        System.out.println("影响数据库的条数:" + result);
    }

    @Test
    public void testUpdate() {
        Dept dept = new Dept();
        dept.setDeptno(41);
        dept.setDname("生产部");
        dept.setLoc("杭州");
        int result = deptDao.update(dept);
        System.out.println("影响数据库的条数:" + result);
    }

    @Test
    public void testDelete() {
        int result = deptDao.delete(41);
        System.out.println("影响数据库的条数:" + result);
    }
}

2.3.6 元の DAO 開発の問題

    dao インターフェース実装クラスのメソッドにはテンプレートメソッドが多数ありますが、これらのコードを抽出してプログラマーの負担を大幅に軽減できるか想像してみてください。
    
    sqlSession のデータベース操作メソッドを呼び出すには、ステートメントの id を指定する必要があります。これは、ここではハードコーディングされており、開発と保守に役立ちません。
    
    SqlSession メソッドを呼び出すときに渡される変数。SqlSession メソッドはジェネリックを使用するため、変数の型が間違って渡された場合でも、コンパイル段階でエラーが報告されず、プログラマーの開発に役立ちません。  
    注: 元の Dao 開発は、Web 段階で説明した Dao 開発と基本的に同じです. それらはすべて Dao インターフェースと Dao 実装クラスを持っていますが、Web 段階の Dao 実装クラスは DBUtils を使用して SQL を操作します. 現在、元の Dao 開発はMybatis の SQL を分離する アウトです、XML マッピング ファイルに記述されているだけです。

2.4 Mapperのプロキシ方式(ポイント)

    Mapper プロキシの開発方法はプログラマーが Mapper インターフェース (Dao インターフェースに相当) を作成するだけでよく、MyBatis フレームワークはインターフェース定義に従ってインターフェースの動的プロキシ オブジェクトを作成します. プロキシ オブジェクトのメソッド本体は、上記の Dao インターフェイス実装クラス メソッド。
    
    プログラマーは、Mapper インターフェースを作成する際にいくつかの開発仕様に従う必要があります。MyBatis は、Mapper インターフェース実装クラスのプロキシ オブジェクトを自動的に生成できます。

2.4.1 開発仕様

    1. Mapper.xml ファイルのネームスペースは、マッパー インターフェースのクラスパスと同じです。

    2. Mapper インターフェースのメソッド名は、Mapper.xml で定義されている各タグの id と同じです。

    3. Mapper インターフェース メソッドのパラメーター タイプは、mapper.xml で定義されている各 sql の parameterType と同じです。

    4. Mapper インターフェース メソッドの戻り値の型は、mapper.xml で定義されている各 sql の resultType と同じです。

注: Mapper.xml マッピング ファイルは、できれば Mapper インターフェースの名前と一致している必要があります。

2.4.2 エンティティクラス

package com.newcapec.entity;

import java.util.Date;

/**
 * Emp实体类
 */
public class Emp {

    private Integer empno;
    private String ename;
    private String job;
    private Integer mgr;
    private Date hiredate;
    private Double sal;
    private Double comm;
    private Integer deptno;

    public Integer getEmpno() {
        return empno;
    }

    public void setEmpno(Integer empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public Integer getMgr() {
        return mgr;
    }

    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    public Double getSal() {
        return sal;
    }

    public void setSal(Double sal) {
        this.sal = sal;
    }

    public Double getComm() {
        return comm;
    }

    public void setComm(Double comm) {
        this.comm = comm;
    }

    public Integer getDeptno() {
        return deptno;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", mgr=" + mgr +
                ", hiredate=" + hiredate +
                ", sal=" + sal +
                ", comm=" + comm +
                ", deptno=" + deptno +
                '}';
    }
}

2.4.3 マッパーインターフェース

package com.newcapec.mapper;

import com.newcapec.entity.Emp;

import java.util.List;

/*
 * Mapper接口相当于我们之前写的Dao接口,只是在Mybatis里面我们习惯这么写而已。
 */
public interface EmpMapper {
    List<Emp> select();

    Emp selectById(Integer empno);

    void insert(Emp emp);

    int update(Emp emp);

    boolean delete(Integer empno);
}
  • バッチ クエリ: メソッドの戻り値は List 型です。これは、SqlSession オブジェクトが selectList() メソッドを呼び出すことを意味します。

  • 単一のクエリ: メソッドの戻り値は単一のエンティティ オブジェクトです。つまり、SqlSession オブジェクトは selectOne() メソッドを呼び出します。

  • 追加、削除、変更:

    1. メソッドの戻り値は void です。これは、SqlSession オブジェクトの挿入、更新、および削除メソッドの戻り値が処理されないことを意味します。

    2. メソッドの戻り値は int 型で、SqlSession オブジェクトの挿入、更新、および削除メソッドの戻り値が直接返されることを示します。

    3. メソッドの戻り値は boolean 型で、SqlSession オブジェクトの insert、update、delete メソッドの戻り値 (データベースに影響を与えるエントリの数) に従って、操作が成功したかどうかを示します。データベースに影響するエントリが 0 より大きい場合は成功を意味し、それ以外の場合は失敗を意味します。

2.4.4 マッパーファイル

<?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接口的全限定名保持一致-->
<mapper namespace="com.newcapec.mapper.EmpMapper">

    <!--
        statementId与Mapper接口的方法名称保持一致
        parameterType的类型必须与方法的参数类型保持一致
        resultType的类型必须与方法的返回值类型保持一致
    -->
    <select id="select" resultType="com.newcapec.entity.Emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
    </select>

    <select id="selectById" parameterType="java.lang.Integer" resultType="com.newcapec.entity.Emp">
        select empno,ename,job,hiredate,mgr,sal,comm,deptno from emp where empno=#{empno}
    </select>

    <insert id="insert" parameterType="com.newcapec.entity.Emp">
        insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
        values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
    </insert>

    <update id="update" parameterType="com.newcapec.entity.Emp">
        update emp set
        ename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno}
        where empno=#{empno}
    </update>

    <delete id="delete" parameterType="java.lang.Integer">
        delete from emp where empno=#{empno}
    </delete>
</mapper>

マッパー ファイルをロードします。

<!-- 加载映射文件的位置 -->
<mappers>
    <mapper resource="mapper/EmpMapper.xml"/>
</mappers>

2.4.5 テスト

package com.newcapec;

import com.newcapec.entity.Emp;
import com.newcapec.mapper.EmpMapper;
import com.newcapec.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Date;
import java.util.List;

public class MapperTest {

    private SqlSession sqlSession;
    private EmpMapper empMapper;

    @Before
    public void before() {
        sqlSession = MybatisUtil.getSession();
        //获取Mapper接口的代理对象
        empMapper = sqlSession.getMapper(EmpMapper.class);
    }

    @After
    public void after() {
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void test() {
        System.out.println(sqlSession);
        System.out.println(empMapper);
    }

    @Test
    public void testSelect() {
        List<Emp> list = empMapper.select();
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

    @Test
    public void testSelectById() {
        Emp emp = empMapper.selectById(7938);
        System.out.println(emp);
    }

    @Test
    public void testInsert() {
        Emp emp = new Emp();
        emp.setEname("小明");
        emp.setJob("职员");
        emp.setSal(4500.0);
        emp.setComm(1000.0);
        emp.setMgr(1);
        emp.setHiredate(new Date());

        empMapper.insert(emp);
    }

    @Test
    public void testUpdate() {
        Emp emp = new Emp();
        emp.setEmpno(7940);
        emp.setEname("小李");
        emp.setJob("秘书");
        emp.setSal(5300.0);
        emp.setComm(1300.0);
        emp.setMgr(1);
        emp.setHiredate(new Date());

        int result = empMapper.update(emp);
        System.out.println("方法的返回值:" + result);
    }

    @Test
    public void testDelete() {
        boolean result = empMapper.delete(7940);
        System.out.println("方法的返回值:" + result);
    }
}

    Mybatis は公式にマッパー プロキシ メソッドを使用してマッパー インターフェイスを開発することを推奨しています. プログラマーはマッパー インターフェイスの実装クラスを記述する必要はありません. マッパー プロキシ メソッドを使用する場合, 入力パラメータは pojo パッケージング オブジェクトまたはマップ オブジェクトを使用して dao の汎用性を確保できます. .

おすすめ

転載: blog.csdn.net/ligonglanyuan/article/details/124272731