mybatis框架入门(一)

mybatis的入门

mybatis的环境搭建

  • 创建maven工程并导入坐标

  • 创建实体类和dao的接口(实体类的成员必须和数据库表格中的字段名称一样)

     

     

  • 创建mybatis的主配置文件SqlMapConfig.xml

     

     

  • 创建映射配置文件WordsDao.xml

     

     

注意事项:

  • 创建WordsDao.xml和WordsDao.java时名称是为了和我们之前的知识保持一致,在mybatis中他把持久层的操作接口名称和映射文件也叫做Mapper,所以,WordsDao和WordsMapper也是一样的

  • 在idea中创建目录的时候,目录和包是不一样的,创建bao时,com.dao是二级结构;若是目录,则是一级结构

  • mybatis的映射配置文件位置必须和dao层接口的包结构一致

  • 映射配置文件的mapper标签namespace的属性的取值必须和dao层接口的全限定类名一致

  • 映射的配置文件的操作配置(select )id属性的取值必须是dao层接口的方法名

  • 如果后三步符合要求,我们在开发中无需再写dao的实现类

mybatis入门案例实现(在上述配置文件已经完整配置好)

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.InputStream;
import java.util.List;
  • 读取主配置文件:

    //读取配置文件时,①可以使用类加载器,他只能读取类路径的配置文件;②可以使用ServletContext对象的getRealPath();
    InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
  • 创建SqlSessionFactory工厂:

    //创建工厂mybatis使用了构建者模式,可以把对象的构建细节隐藏,使使用者直接调用方法即可拿到对象
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
  • 创建SqlSession对象

    //生产SqlSession使用了工厂模式,可以解耦类之间的关系
    SqlSession sqlSession = factory.openSession();
  • 创建Dao接口的代理对象

    //创建dao接口实现类使用了代理模式,不修改源码的基础上对已有的方法功能增强
    WordsDao wordsDao = sqlSession.getMapper(WordsDao.class);
  • 使用代理对象执行方法

    List<Words> words = wordsDao.findAll();
            for (Words word : words) {
                System.out.println(word);
            }
  • 释放资源

    sqlSession.close();
    in.close();

    完成的代码:

    package com.test;
    ​
    ​
    import com.dao.WordsDao;
    import com.domain.Words;
    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.InputStream;
    import java.util.List;
    ​
    /**
     * @author xusha
     *
     * mybatis入门案例
     */
    public class MybatisTest {
        public static void main(String[] args) throws Exception {
            //1、读取配置文件
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2、创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
            //3、使用工厂创建SqlSession对象
            SqlSession sqlSession = factory.openSession();
            //4、使用SqlSession对象创建Dao接口的代理对象
            WordsDao wordsDao = sqlSession.getMapper(WordsDao.class);
            //5、使用代理对象执行方法
            List<Words> words = wordsDao.findAll();
            for (Words word : words) {
                System.out.println(word);
            }
            //6、释放资源
            sqlSession.close();
            in.close();
        }
    }
  • 注意事项:

    • 可以使用注解的方式优化一些必要的代码

    在我们的主配置文件,修改指定的映射配置文件,这样指定的映射配置文件就可以删除

    <!-- 指定映射配置文件的位置,映射配置文件指的是每个Dao独立的配置文件
                <mapper resource="com/dao/WordsDao.xml" />
        -->
        <!-- 如果使用注解的方式,指定映射配置文件可以删除,在接口的方法上添加注解,如
                @Select("select * from words")
                而且下面的resource修改为class,指定被注解的dao全限定类名称
                <mapper class="com.dao.WordsDao" />
        -->
        <mappers>
    <!--        <mapper resource="com/dao/WordsDao.xml" />-->
            <mapper class="com.dao.WordsDao" />
      </mappers>
    • 或者我们使用接口实现类完成查询结果:我们需要在dao包下创建一个impl包,新建接口的实现类,重写接口的方法(findAll)

    public class WordsDaoImpl implements WordsDao{
        private SqlSessionFactory factory;
        public WordsDaoImpl(SqlSessionFactory factory){
            this.factory = factory;
        }
        
        @Override
        public List<Words> findAll(){
            //1、使用工厂创建SqlSession对象
            SqlSession session = factory.openSession();
            //2、使用session执行查询所有方法
            List<Words> words = session.selectList("com.dao.WordsDao.findAll");
            session.close();
            //3、返回查询结果
            return words;
        }
    }

    由于我们在上述测试类中的main函数中已经有了工厂对象,我们就可以直接传递对象参数,后执行实现类的方法,而且还没有session对象,也不用关闭,对比之后的代码

    package com.test;
    
    
    import com.dao.WordsDao;
    import com.domain.Words;
    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.InputStream;
    import java.util.List;
    
    /**
     * @author xusha
     *
     * mybatis入门案例
     */
    public class MybatisTest {
        public static void main(String[] args) throws Exception {
            //1、读取配置文件
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2、创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
            //3、创建实现类对象
            WordsDaoImpl wordsDaoImpl = new WordsDaoImpl(factory);
            //4、使用对象执行方法
            List<Words> words = wordsDaoImpl.findAll();
            for (Words word : words) {
                System.out.println(word);
            }
            //5、释放资源
            in.close();
        }
    }

    使用指定的映射配置文件实现mybatis的增删改查等功能

    CURD功能都是使用代理对象实现的(使用单元测试功能测试每一个功能,另外增加一个聚合函数的实现和一个模糊查询的功能)

    完成这些功能分为以下几个步骤:(主配置已配好)

  • 实体类Words.java:成员变量尽量和数据库表的字段名一样,每个成员的setter和getter方法,另外增加一个toString()方法

package com.domain;

import java.io.Serializable;

/**
 * @author 小沙砾
 */
public class Words implements Serializable {
    private Integer id;
    private String word;
    private String translation;
    private String introduction;
    private String add_time;
    private Integer star;

    @Override
    public String toString() {
        return "com.domain.Words{" +
                "id=" + id +
                ", word='" + word + '\'' +
                ", translation='" + translation + '\'' +
                ", introduction='" + introduction + '\'' +
                ", add_time='" + add_time + '\'' +
                ", star=" + star +
                '}';
    }

    public Integer getId() {
        return id;
    }

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

    public String getWord() {
        return word;
    }

    public void setWord(String word) {
        this.word = word;
    }

    public String getTranslation() {
        return translation;
    }

    public void setTranslation(String translation) {
        this.translation = translation;
    }

    public String getIntroduction() {
        return introduction;
    }

    public void setIntroduction(String introduction) {
        this.introduction = introduction;
    }

    public String getAdd_time() {
        return add_time;
    }

    public void setAdd_time(String add_time) {
        this.add_time = add_time;
    }

    public Integer getStar() {
        return star;
    }

    public void setStar(Integer star) {
        this.star = star;
    }
}
  • dao层的接口类的抽象方法需要包含4个功能CRUD

package com.dao;

import com.domain.Words;

import java.util.List;

/**
 * @author 小沙砾
 *
 * 用户的持久层接口
 */
public interface WordsDao {
    /**
     * 查询所有信息
     * @return
     */
    List<Words> findAll();

    /**
     * 保存信息
     * @param words
     */
    void saveWords(Words words);

    /**
     * 更新信息
     * @param words
     */
    void updateWords(Words words);

    /**
     * 删除信息
     * @param id
     */
    void deleteWords(Integer id);
    
    /**
     * 根据id查询信息
     * @return
     */
    List<Words> findById(Integer id);

    /**
     * 根据word模糊查询信息
     * @return
     */
    List<Words> findByWord(String word);

    /**
     * 统计信息的记录数
     * @return
     */
    int countInfo();
}
  • 主配置中需要指定的映射配置文件WordsDao.xml,如果使用到实体类的成员变量名,需要在标签上指定parameterType="全限类限定名",成员变量使用#{成员变量名}

<?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.dao.WordsDao">
    <!-- 配置查询所有 -->
    <select id="findAll" resultType="com.domain.Words">
        select * from words;
    </select>

    <!-- 保存信息 -->
    <insert id="saveWords" parameterType="com.domain.Words">
        insert into words(id, word, translation, introduction, group_id, add_time, star)
        values(#{id}, #{word}, #{translation}, #{introduction}, 1, #{add_time}, #{star});
    </insert>

    <!-- 更新信息 -->
    <update id="updateWords" parameterType="com.domain.Words">
        update words
        set star = #{star}
        where id = #{id};
    </update>

    <!-- 删除信息 -->
    <delete id="deleteWords" parameterType="int">
        delete
        from words
        where id = #{wid}
    </delete>
    
    <!-- 根据id查询信息 -->
    <select id="findById" parameterType="int" resultType="com.domain.Words">
        select * from words where id = #{wid};
    </select>

    <!-- 根据名称模糊查询信息 -->
    <select id="findByWord" parameterType="String" resultType="com.domain.Words">
        select * from words where word like #{word};
    </select>

    <!-- 统计信息的记录数 -->
    <select id="countInfo" resultType="int">
        select count(id) from words;
    </select>
</mapper>

 

  • 测试类中包含各种测试,其中包含CURD功能测试,为了测试CURD功能,也可以优化一些代码,如各种对象的创建和销毁,使得我们测试的方法只包含主要测试的部分

package com.test;


import com.dao.WordsDao;
import com.domain.Words;
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.InputStream;
import java.util.List;

/**
 * @author 小沙砾
 *
 * mybatis入门案例
 */
public class MybatisTest {
    private InputStream in;
    private SqlSessionFactoryBuilder builder;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private WordsDao wordsDao;

    @Before   //用于在测试方法执行之前执行的
    public void init() throws Exception {
        //1、读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2、创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(in);
        //3、使用工厂创建SqlSession对象
        sqlSession = factory.openSession();
        //4、使用SqlSession对象创建Dao接口的代理对象
        wordsDao = sqlSession.getMapper(WordsDao.class);
    }

    @After   //用于在测试方法执行之后执行的
    public void destroy(){
        //6、释放资源
        if(sqlSession != null){
            try{
                sqlSession.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        if(in != null){
            try{
                in.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testFindAll() {
        //5、使用代理对象执行方法
        List<Words> words = wordsDao.findAll();
        for (Words word : words) {
            System.out.println(word);
        }
    }

    @Test
    public void testSaveWords() {
        Words words = new Words();
        words.setId(8);
        words.setWord("come on!");
        words.setTranslation("加油!");
        words.setIntroduction("语气词");
        words.setAdd_time("2020-03-20");
        words.setStar(1);

        //5、执行保存方法
        wordsDao.saveWords(words);

        //事务提交
        sqlSession.commit();
    }

    @Test
    public void testUpdateWords() {
        Words words = new Words();
        words.setId(8);
        words.setWord("come on!");
        words.setTranslation("加油!");
        words.setIntroduction("语气词");
        words.setAdd_time("2020-03-20");
        words.setStar(2);

        //5、执行更新方法
        wordsDao.updateWords(words);

        //事务提交
        sqlSession.commit();
    }

    @Test
    public void testDeleteWords() {
        //5、执行删除方法
        wordsDao.deleteWords(8);

        //事务提交
        sqlSession.commit();
    }
    
    @Test
    public void testFindById() {
        //5、执行根据id查询信息方法
        List<Words> words = wordsDao.findById(7);
        for (Words word : words) {
            System.out.println(word);
        }
    }

    @Test
    public void testFindByWord() {
        //5、执行根据word名称模糊查询信息
        List<Words> words = wordsDao.findByWord("%w%");
        for (Words word : words) {
            System.out.println(word);
        }
    }

    @Test
    public void testCountInfo(){
        //5、执行统计信息的记录数的方法
        Integer count = wordsDao.countInfo();
        System.out.println(count);
    }
}

在Dao层使用实现接口类实现mybatis的CURD功能

  • 根据上述说明,可以知道在dao层可以创建执行数据库session对象,即可在dao层的接口实现类里执行重写的方法来执行数据库操作的语句,实体类和指定映射配置文件不需要改变。

  • 接口实现类WordsDaoImpl:实现接口类的抽象方法,用成员变量session调用自己的实现方法

package com.dao.impl;

import com.dao.WordsDao;
import com.domain.Words;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

public class WordsDaoImpl implements WordsDao {
    private SqlSessionFactory factory;

    public WordsDaoImpl(SqlSessionFactory factory){
        this.factory = factory;
    }

    public List<Words> findAll() {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session执行查询的所有方法
        List<Words> words = session.selectList("com.dao.WordsDao.findAll");
        session.close();
        //3、返回查询结果
        return words;
    }

    public void saveWords(Words words) {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行保存方法
        session.insert("com.dao.WordsDao.saveWords", words);
        //3、事务提交
        session.commit();
        session.close();
    }

    public void updateWords(Words words) {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行更新方法
        session.update("com.dao.WordsDao.updateWords", words);
        //3、事务提交
        session.commit();
        session.close();
    }

    public void deleteWords(Integer id) {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行删除方法
        session.delete("com.dao.WordsDao.deleteWords", id);
        //3、事务提交
        session.commit();
        session.close();
    }

    public Words findById(Integer id) {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行查询方法
        Words words = session.selectOne("com.dao.WordsDao.findById", id);
        session.close();
        return words;
    }

    public List<Words> findByWord(String word) {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行模糊查询方法
        List<Words> words = session.selectList("com.dao.WordsDao.findByWord", word);
        session.close();
        return words;
    }

    public int countInfo() {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行统计信息记录数方法
        Integer count = session.selectOne("com.dao.WordsDao.countInfo");
        session.close();
        return count;
    }
}
  • 相应的测试类的单元测试方法可以减少不必要的代码

package com.test;


import com.dao.WordsDao;
import com.dao.impl.WordsDaoImpl;
import com.domain.Words;
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.InputStream;
import java.util.List;

/**
 * @author 小沙砾
 *
 * mybatis入门案例
 */
public class MybatisTest {
    private InputStream in;
    private SqlSessionFactoryBuilder builder;
    private SqlSessionFactory factory;
    //实现类对象
    private WordsDaoImpl wordsDaoImpl;

    @Before   //用于在测试方法执行之前执行的
    public void init() throws Exception {
        //1、读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2、创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(in);
        //3、创建实现类对象
        wordsDaoImpl = new WordsDaoImpl(factory);
    }

    @After   //用于在测试方法执行之后执行的
    public void destroy(){
        //6、释放资源
        if(in != null){
            try{
                in.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testFindAll() {
        //4、使用对象执行方法
        List<Words> words = wordsDaoImpl.findAll();
        for (Words word : words) {
            System.out.println(word);
        }
    }

    @Test
    public void testSaveWords() {
        Words words = new Words();
        words.setWord("smartphone");
        words.setTranslation("智能手机");
        words.setIntroduction("名词");
        words.setAdd_time("2020-03-20");
        words.setStar(1);
        System.out.println("保存之前的"+words);  //其中的id=null
        //5、执行保存方法
        wordsDaoImpl.saveWords(words);
        System.out.println("保存之后的"+words);   //其中的id有具体的值
    }

    @Test
    public void testUpdateWords() {
        Words words = new Words();
        words.setId(10);
        words.setStar(4);

        //5、执行更新方法
        wordsDaoImpl.updateWords(words);
    }

    @Test
    public void testDeleteWords() {
        //5、执行删除方法
        wordsDaoImpl.deleteWords(2);
    }

    @Test
    public void testFindById() {
        //5、执行根据id查询信息方法
        Words words = wordsDaoImpl.findById(7);
        System.out.println(words);
    }

    @Test
    public void testFindByWord() {
        //5、执行根据word名称模糊查询信息
        List<Words> words = wordsDaoImpl.findByWord("%w%");
        for (Words word : words) {
            System.out.println(word);
        }
    }

    @Test
    public void testCountInfo(){
        //5、执行统计信息的记录数的方法
        Integer count = wordsDaoImpl.countInfo();
        System.out.println(count);
    }
}

主配置文件的一些配置的要点

使用数据库连接为例

  • 直接配置数据库环境然后在连接

  • 使用properties配置,在标签内部给定数据库连接的信息

  • 使用外部配置文件,然后在properties的resource属性或者是url属性指定外部配置文件的信息

注意事项:文件中有如何使用填写的信息

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

    <!-- 配置properties -->
    <!-- 可以在标签内部配置数据库连接的信息,也可以通过属性引用外部配置文件信息
        resource属性:
            用于指定配置文件的位置,是按照类路径的写法,并且必须存在于类路径下
        url属性:
            是一个统一资源定位符,是由协议、地址、端口、URI组成
            url="file:///D:/一连串路径/jdbcConfig.properties"
     -->
    <properties resource="jdbcConfig.properties">
<!--        <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<!--        <property name="url" value="jdbc:mysql://localhost:3306/myword"/>-->
<!--        <property name="username" value="root"/>-->
<!--        <property name="password" value="123456"/>-->
    </properties>

    <!-- 配置环境 -->
    <environments default="mysql">
        <!-- 配置MySQL的环境 -->
        <environment id="mysql">
            <!-- 配置事务类型 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <!-- 如果使用标签内的信息value的值必须和properties配置的property的id变量名称
                     如果使用外部配置信息,value的值必须和外部配置文件的变量一致
                -->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 指定映射配置文件的位置,映射配置文件指的是每个Dao独立的配置文件
            <mapper resource="com/dao/WordsDao.xml" />
    -->
    <!-- 如果使用注解的方式,指定映射配置文件可以删除,在接口的方法上添加注解,如
            @Select("select * from words")
            而且下面的resource修改为class,指定被注解的dao全限定类名称
            <mapper class="com.dao.WordsDao" />
    -->
    <mappers>
        <mapper resource="com/dao/WordsDao.xml" />
<!--        <mapper class="com.dao.WordsDao" />-->
    </mappers>
</configuration>

mybatis配置数据库连接池

mybatis提供了3种数据库连接池的配置方式

  • 配置的位置

    • 主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式,type属性值如下

      • POOLED 采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现

      • UNPOOLED 采用传统的获取连接的方式,虽然也实现了javax.sql.DataSource接口,但是并没有实现池的思想

      • JNDI 采用服务器提供的JDNI技术实现,来获取DataSource对象,不同的服务器所能拿到的DataSource是不一样的

        注意:如果不是web或者maven的war工程,是不能使用的

mybatis动态查询数据库表格信息

像一些有多重条件的或者是in集合的sql语句,我们可以采用一些特定的标签,以下只举例and条件和in集合(这里是使用dao层对象),这里还会使用封装

  • 我们可以创建一个类来辅助我们的实体类,这里是创建一个QueryVo类

package com.domain;

import java.util.List;

public class QueryVo {
    private Words words;
    private List<Integer> ids;

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }

    public Words getWords() {
        return words;
    }

    public void setWords(Words words) {
        this.words = words;
    }
}
  • 我们在dao层接口定义两个抽象方法:多重条件和集合查询

package com.dao;

import com.domain.QueryVo;
import com.domain.Words;

import java.util.List;

/**
 * @author 小沙砾
 *
 * 用户的持久层接口
 */
public interface WordsDao {
    /**
     * 查询所有信息
     * @return
     */
    List<Words> findAll();

    /**
     * 根据queryVo中的条件查询信息
     * @param vo
     * @return
     */
    List<Words> findWordsByVo(QueryVo vo);

    /**
     * 根据条件获取信息
     * @param words: 参数是可变的(参数个数不定)
     * @return
     */
    List<Words> findByConditions(Words words);

    /**
     * 根据queryVo中的id集合查询信息
     * @param vo
     * @return
     */
    List<Words> findWordsByInIds(QueryVo vo);
}
  • 接口实现类

package com.dao.impl;

import com.dao.WordsDao;
import com.domain.QueryVo;
import com.domain.Words;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

public class WordsDaoImpl implements WordsDao {
    private SqlSessionFactory factory;

    public WordsDaoImpl(SqlSessionFactory factory){
        this.factory = factory;
    }

    public List<Words> findAll() {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session执行查询的所有方法
        List<Words> words = session.selectList("com.dao.WordsDao.findAll");
        session.close();
        //3、返回查询结果
        return words;
    }

    public List<Words> findWordsByVo(QueryVo vo) {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行根据条件查询的方法
        List<Words> res = session.selectList("com.dao.WordsDao.findWordsByVo", vo);
        session.close();
        return res;
    }

    public List<Words> findByConditions(Words words){
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行根据条件查询的方法
        List<Words> res = session.selectList("com.dao.WordsDao.findByConditions", words);
        session.close();
        return res;
    }

    public List<Words> findWordsByInIds(QueryVo vo) {
        //1、使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2、使用session对象执行根据条件查询的方法
        List<Words> res = session.selectList("com.dao.WordsDao.findWordsByInIds", vo);
        session.close();
        return res;
    }
}
  • 指定映射配置文件里需要将words结果集封装成Map

<?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.dao.WordsDao">
    <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
    <resultMap id="wordsMap" type="com.domain.Words">
        <!-- 主键的对应字段 -->
        <id property="id" column="id"></id>
        <!-- 非主键的对应字段 -->
        <result property="word" column="word"></result>
        <result property="translation" column="translation"></result>
        <result property="introduction" column="introduction"></result>
        <result property="add_time" column="add_time"></result>
        <result property="star" column="star"></result>
    </resultMap>

    <!-- 配置查询所有 -->
    <select id="findAll" resultMap="wordsMap">
        select * from words;
    </select>

    <!-- 根据queryVo的条件模糊查询信息 -->
    <select id="findWordsByVo" parameterType="com.domain.QueryVo" resultType="com.domain.Words">
        select * from words where word like #{words.word};
    </select>

    <!-- 动态sql语句:根据条件获取信息 -->
    <select id="findByConditions" resultType="com.domain.Words" parameterType="com.domain.Words">
        select * from words where 1=1
        <if test="word != null">
            and word = #{word}
        </if>
    </select>

    <!-- 动态sql语句:使用queryVo中的id集合实现查询信息 -->
    <select id="findWordsByInIds" resultMap="wordsMap" parameterType="com.domain.QueryVo">
        select * from words
        <where>
            <if test="ids != null and ids.size()>0">
                <foreach collection="ids" open="and id in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>
</mapper>

 

  • 单元测试类

package com.test;


import com.dao.WordsDao;
import com.dao.impl.WordsDaoImpl;
import com.domain.QueryVo;
import com.domain.Words;
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.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 小沙砾
 *
 * mybatis入门案例
 */
public class MybatisTest {
    private InputStream in;
    private SqlSessionFactoryBuilder builder;
    private SqlSessionFactory factory;
    //实现类对象
    private WordsDaoImpl wordsDaoImpl;

    @Before   //用于在测试方法执行之前执行的
    public void init() throws Exception {
        //1、读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2、创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(in);
        //3、创建实现类对象
        wordsDaoImpl = new WordsDaoImpl(factory);
    }

    @After   //用于在测试方法执行之后执行的
    public void destroy(){
        //6、释放资源
        if(in != null){
            try{
                in.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testFindAll() {
        //4、使用对象执行方法
        List<Words> words = wordsDaoImpl.findAll();
        for (Words word : words) {
            System.out.println(word);
        }
    }

    @Test
    public void testFindWordsByVo() {
        QueryVo vo = new QueryVo();
        Words words = new Words();
        words.setWord("%w%");
        vo.setWords(words);
        //5、执行根据word名称模糊查询信息
        List<Words> res = wordsDaoImpl.findWordsByVo(vo);
        for (Words re : res) {
            System.out.println(re);
        }
    }

    @Test
    public void testFindByCondition(){
        Words words = new Words();
        words.setWord("computer");
        //5、执行根据条件查询的方法
        List<Words> res = wordsDaoImpl.findByConditions(words);
        for (Words re : res) {
            System.out.println(re);
        }
    }

    @Test
    public void testFindWordsByInIds(){
        QueryVo vo = new QueryVo();
        ArrayList<Integer> arr = new ArrayList<Integer>();
        arr.add(1);
        arr.add(8);
        arr.add(7);
        arr.add(10);
        arr.add(9);
        vo.setIds(arr);
        List<Words> res = wordsDaoImpl.findWordsByInIds(vo);
        for (Words re : res) {
            System.out.println(re);
        }
    }
}

 

mybatis中多表之间的关系的实现

  • mybatis中多表之间的一对一关系

    • 两个表的实体类可以像往常一样创建,但是在子表(从表)创建主表实体类对象的引用,以下显示子表实体类

    package com.domain;
    
    import java.io.Serializable;
    
    /**
     * @author 小沙砾
     */
    public class Words implements Serializable {
        private Integer id;
        private String word;
        private Integer group_id;
    
        //从表实体应该有一个主表实体的对象引用
        private Groups groups;
    
        public Groups getGroups() {
            return groups;
        }
    
        public void setGroups(Groups groups) {
            this.groups = groups;
        }
    
        public Integer getGroup_id() {
            return group_id;
        }
    
        public void setGroup_id(Integer group_id) {
            this.group_id = group_id;
        }
    
        @Override
        public String toString() {
            return "Words{" +
                    "id=" + id +
                    ", word='" + word + '\'' +
                    ", group_id='" + group_id + '\'' +
                    '}';
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getWord() {
            return word;
        }
    
        public void setWord(String word) {
            this.word = word;
        }
    
       
    • 这一步需要在子表指定映射配置文件封装一个Map集合

    <?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.dao.WordsDao">
        <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
        <resultMap id="wordsMap" type="com.domain.Words">
            <!-- 主键的对应字段 -->
            <id property="id" column="id"></id>
            <!-- 非主键的对应字段 -->
            <result property="word" column="word"></result>
            <result property="group_id" column="group_id"></result>
        </resultMap>
    
        <!-- 定义封装Words和Groups的resultMap -->
        <resultMap id="wordsGroupsMap" type="com.domain.Words">
            <!-- 前面的名称对应的是实体类的成员变量,后面的名称对应的是sql结果集或者表格的列名称 -->
            <!-- 主键的对应字段 -->
            <id property="id" column="id"></id>
            <!-- 非主键的对应字段 -->
            <result property="word" column="word"></result>
            <result property="group_id" column="group_id"></result>
            <!-- 一对一的关系映射,配置封装Groups的内容 -->
            <association property="groups" column="gid" javaType="com.domain.Groups">
                <!-- 前面的名称对应的是javaType的成员变量,后面的名称对应的是sql结果集的列名称 -->
                <id property="id" column="gid"></id>
                <result property="name" column="gname"></result>
                <result property="add_time" column="gadd_time"></result>
            </association>
        </resultMap>
    
        <!-- 配置查询所有 -->
        <select id="findAll" resultType="com.domain.Words">
            select * from words;
        </select>
    
        <!-- 配置查询所有大有分组信息的单词信息 一对一的关系的实现 -->
        <select id="findAllWordsGroups" resultType="com.domain.WordsGroups">
            select w.*, g.id as gid, g.name as gname
            from words as w, groups as g
            where w.group_id = g.id
        </select>
    
        <!-- 配置查询所有大有分组信息的单词信息 -->
        <select id="findAllByMap" resultMap="wordsGroupsMap">
            select w.*, g.id as gid, g.name as gname, g.add_time as gadd_time
            from words as w, groups as g
            where w.group_id = g.id
        </select>
    </mapper>
    • 接口类、接口实现类、测试类方法像往常一样实现,但是在一对一的抽象方法或者是其重写方法的返回值必须是子表实体类类型

  • mybatis中多表之间的一对多关系

    • 两个表的实体类可以像往常一样创建,但是在主表创建子表实体类对象的引用集合,以下显示主表实体类

    package com.domain;
    
    import java.io.Serializable;
    import java.util.List;
    
    public class Groups implements Serializable {
        private Integer id;
        private String name;
        private String add_time;
    
        //一对多关系映射,主表实体应该包含从表实体的集合引用
        private List<Words> words;
    
        public List<Words> getWords() {
            return words;
        }
    
        public void setWords(List<Words> words) {
            this.words = words;
        }
    
        @Override
        public String toString() {
            return "Groups{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", add_time='" + add_time + '\'' +
                    '}';
        }
    
        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 getAdd_time() {
            return add_time;
        }
    
        public void setAdd_time(String add_time) {
            this.add_time = add_time;
        }
    }
    • 这一步需要在主表指定映射配置文件封装一个Map集合

    <?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.dao.GroupsDao">
        <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
        <resultMap id="groupsMap" type="com.domain.Groups">
            <!-- 主键的对应字段 -->
            <id property="id" column="id"></id>
            <!-- 非主键的对应字段 -->
            <result property="name" column="name"></result>
            <result property="add_time" column="add_time"></result>
        </resultMap>
    
        <!-- 定义Groups的resultMap -->
        <resultMap id="groupsWordsMap" type="com.domain.Groups">
            <id property="id" column="gid"></id>
            <result property="name" column="gname"></result>
            <result property="add_time" column="gadd_time"></result>
            <!-- 配置groups对象中words集合的映射 -->
            <collection property="words" ofType="com.domain.Words">
                <id property="id" column="id"></id>
                <result property="word" column="word"></result>
                <result property="group_id" column="group_id"></result>
            </collection>
        </resultMap>
    
        <!-- 查询每个分组下的所有单词信息 -->
        <select id="findGroupsInWords" resultMap="groupsWordsMap">
            select w.*, g.id as gid, g.name as gname, g.add_time as gadd_time
            from groups g left outer join words w
            on g.id = w.group_id;
        </select>
    
    </mapper>

     

    • 接口类、接口实现类、测试类方法像往常一样实现,但是在一对一的抽象方法或者是其重写方法的返回值必须是主表实体类类型

posted @ 2020-04-08 19:00  xsha_h  阅读(167)  评论(0编辑  收藏  举报