欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis学习笔记(二)CRUD操作(查询操作基础)

程序员文章站 2022-05-23 19:49:59
...

首发于我的博客 和尚的博客
本篇主要讲解查询操作的结果集处理、映射文件里命名空间设置,SQL语句中resultMap,resultType等属性意思、MyBatis的传统和接口代理模式。


源码获取github

1.整体结构目录

MyBatis学习笔记(二)CRUD操作(查询操作基础)

  • SkillDao.java接口含一些方法
  • SkillDaoImpl.java是SkillDao的实现类
  • Skill.java是持久化类(实体Bean)
  • SkillMapper.xml是Skill持久化类的映射文件(含SQL语句操作等)
  • MyBatisTest.java测试类
  • jdbc.properties数据库的属性文件
  • log4j.properties日志框架配置(在控制台显示sql语句等信息)
  • mybatis-config.xml核心配置文件

2.数据库属性文件

jdbc.properties

jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/cy42_mss
jdbc.mysql.username=root
jdbc.mysql.password=root

3.核心配置文件

mybatis-config.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>
    <!--加载属性文件 -->
    <properties resource="jdbc.properties"/>
    <!--自定义设置类型的别名,也就是resultMap里的type,避免包名已修改,在映射文件里修改多处地方-->
    <typeAliases>
        <!-- 方式一、com.hs.model.Skill这个类设置了别名hs,之后要用这个的话,直接写hs -->
        <!--<typeAlias type="com.hs.model.Skill" alias="hs"/> -->
        <!-- 方式二、com.hs.model这个包下的类,要用的时候直接写类名,比如用com.hs.model.Skill,直接写Skill -->
        <package name="com.hs.model"/>
    </typeAliases>
    <!--配置数据库的环境-->
    <environments default="development">
        <environment id="development">
            <!--事务管理器:保证数据的完整性和一致性   关键信息  -->
            <!--框架:默认情况下CUD操作需要  手动提交事务
            (如同在Navicat中表中输入了数据,没有点那个小√,就是没有提交事务,
            但是输入insert语句,就自动提交事务了)  -->
            <transactionManager type="JDBC" />
            <!-- mybatis提供了3种数据源类型,分别是:POOLED,UNPOOLED,JNDI -->
            <!-- POOLED 表示支持JDBC数据源连接池 -->
            <!-- UNPOOLED 表示不支持数据源连接池 -->
            <!-- JNDI 表示支持外部数据源连接池 -->
            <!--使用的是连接池:百度java如何实行连接池的原理?  -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.mysql.driver}" />  <!--获取值,${属性文件里的变量名},也可以直接写值-->
                <property name="url" value="${jdbc.mysql.url}" />  <!--获取值,${属性文件里的变量名},也可以直接写值-->
                <property name="username" value="${jdbc.mysql.username}" /> <!--获取值,${属性文件里的变量名},也可以直接写值-->
                <property name="password" value="${jdbc.mysql.password}" /> <!--获取值,${属性文件里的变量名},也可以直接写值-->
            </dataSource>
        </environment>
    </environments>

    <!--加载映射文件 ,也就是含sql语句的文件-->
    <mappers>
        <!--告知映射文件方式1,一个一个的配置-->
        <mapper resource="com/hs/model/SkillMapper.xml"/>
        <!-- 告知映射文件方式2,自动扫描包内的Mapper接口与配置文件 -->
        <!--<package name="com.hs.model"/>-->
    </mappers>
</configuration>

4.封装好的工具类

MyBatisUtils.java

package com.hs.util;
/**
 * 知识点:
 * final修饰类:不能被继承
 * 修饰方法:不能被重写
 * 修饰变量:常量不可用变,但如果是对象,对象里的值可以变
 *
 */
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 MyBatisUtils() { }  //不允许实例化

    private static final String PATH = "mybatis-config.xml";
    private static InputStream inputStream;
    private static SqlSessionFactory sqlSessionFactory;

    static { //1.静态代码块,只是加载一次
        try {
            //输入流 读文件
            //1.读取核心配置文件
            inputStream = Resources.getResourceAsStream(PATH);
            //2.创建SqlSession工厂(SqlSessionFactory)相当于Connection
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("加载核心配置文件失败");
        }
    }

    /**
     * 获取sqlsession
     * @return
     */
    public static SqlSession getSqlsession() {
        //3.获取SqlSession 相当于执行SQL语句对象PreparedStament预处理对象
        //***** SqlSession完成所有的持久化操作CRUD
        return sqlSessionFactory.openSession();
    }

    /**
     * 关闭资源
     * @param sqlSession
     */
    public static void closeSqlSession(SqlSession sqlSession) {
        if (sqlSession != null) {
            sqlSession.close();
        }
    }
}

5.持久化类

为了讲出来一些知识点,持久化类的属性名没有和数据库的字段名一样,正常应该是一样的

Skill.java

package com.hs.model;

public class Skill {
    private Integer skillid;
    private String skillname;
    private Integer num;

    public Integer getSkillid() {
        return skillid;
    }

    public void setSkillid(Integer skillid) {
        this.skillid = skillid;
    }

    public String getSkillname() {
        return skillname;
    }

    public void setSkillname(String skillname) {
        this.skillname = skillname;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "Skill{" +
                "skillid=" + skillid +
                ", skillname='" + skillname + '\'' +
                ", num=" + num +
                '}';
    }
}

6.XML映射文件

SQL映射文件经常含一些元素

  • parameterType—-接收的参数类型,简写方式见mybatis官方文档中,别名和映射的类型那块
  • parameterMap没有人用了!!!!!
  • resultType—-语句执行完毕返回的结果集类型
  • resultMap—-语句执行完毕返回的结果集,这是一个标签,找它对应的标签,对这个结果集进行处理,里面的type就是相应的返回类型
  • sql—-提取公共的SQL代码
  • insert—-映射插入语句
  • update—-映射更新语句
  • delete—-映射删除语句
  • select—-映射查询语句

SkillMapper.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">
<!--namespace=命名空间,唯一不重复-->
<mapper namespace="com.hs.model.Skill"> <!--命名空间规则
传统模式:(持久化类(实体化Bean)的类名全路径com.hs.Skill)
接口代理模式:接口的全路径-->

    <!--查询的字段,并没有优化,下个专题进行优化-->
    <!--当你传递的是“一个”简单的数据类型的形参的时候,那么你的${任意名字},sql语句后面不要加   ;   -->
    <select id="getMap01ByPk" parameterType="_int" resultType="map">
        select skill_id,skill_name,num from skill where skill_id = #{sadsa}
    </select>
    <select id="getMap02ByPk" parameterType="_int" resultType="map">
        select skill_id skillid,skill_name skill_name ,num number from skill where skill_id = #{skill_id}
    </select>
    <!--只能对结果集的结果操作进行处理,autoMapping="true"默认映射,默认为true,重写字段名会覆盖默认的,若false就不会映射默认字段(只映射出自己写的别名)-->
    <resultMap id="MapResultMapper" type="map" autoMapping="true">
        <result column="skill_id" property="id"/>   <!--column为结果集里的字段名,property为自己要映射(变成)的字段名-->
        <result column="skill_name" property="name"/>
        <result column="num" property="number"/>
    </resultMap>
    <select id="getMap03ByPk" parameterType="_int" resultMap="MapResultMapper">
        select skill_id,skill_name ,num from skill where skill_id = #{skill_id}
    </select>
    <!--1.别名方法,属性和字段名一致,可以完成自动映射-->
    <select id="getSkill01ByPk" parameterType="int" resultType="com.hs.model.Skill">
        select skill_id skillid,skill_name skillname,num from skill where skill_id = #{adsa}
    </select>
    <!--2.resultMap标签找对应id的标签,利用结果集,进行转换,jdbcType和javaType可以不用写,名字见jdbc类型和Java 类型对应http://www.mybatis.org/mybatis-3/zh/configuration.html#typeAliases-->
    <resultMap id="SkillResultMapper" type="com.hs.model.Skill">
        <id column="skill_id" jdbcType="INTEGER" property="skillid" javaType="java.lang.Integer"/>
        <result column="skill_name" jdbcType="VARCHAR" property="skillname" javaType="java.lang.String"/>
        <result column="num" property="num"/>
    </resultMap>
    <select id="getSkill02ByPk" parameterType="int" resultMap="SkillResultMapper">
        select skill_id,skill_name,num from skill where skill_id = #{adsa}
    </select>

    <!--一条一条的为map-->
    <select id="getSkillList01ByAll" resultType="map">
        select skill_id,skill_name,num from skill
    </select>
    <select id="getSkillList02ByAll" resultMap="SkillResultMapper">
        select skill_id,skill_name,num from skill
    </select>
</mapper>

7.接口

SkillDao.java

package com.hs.dao;

import com.hs.model.Skill;

import java.util.List;
import java.util.Map;

public interface SkillDao {
    /**
     * 处理结果集为Map类型
     * @param skillid
     * @return
     */
    Map<String, Object> getMap01ByPk(int skillid);
    /**
     * 处理结果集为Map类型—通过给字段取别名方式
     * @param skillid
     * @return
     */
    Map<String, Object> getMap02ByPk(int skillid);

    /**
     * 处理结果集为Map类型—通过resultMap标签处理
     * @param skillid
     * @return
     */
    Map<String, Object> getMap03ByPk(int skillid);

    /**
     * 处理结果集为自定义的类Skill—通过给字段取别名方式
     * @param skillid
     * @return
     */
    Skill getSkill01ByPk(int skillid);

    /**
     * 处理结果集为自定义的类Skill—resultMap标签处理
     * @param skillid
     * @return
     */
    Skill getSkill02ByPk(int skillid);

    /**
     * 处理结果集为集合(list)
     * @param skillid
     * @return
     */
    List<Map<String, Object>> getSkillList01ByAll();

    /**
     * 处理结果集为集合(list)—通过resultMap
     * @param skillid
     * @return
     */
    List<Map<String, Object>> getSkillList02ByAll();

}

8.接口实现类

SkillDaoImpl.java

package com.hs.dao;

import com.hs.model.Skill;
import com.hs.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;

import java.util.List;
import java.util.Map;

public class SkillDaoImpl implements SkillDao {

    /*
    * 关键步骤:定位执行SQL语句***如何定位 (namespace+"."+id)
    * 因为命名空间是Bean的路径,所以下面的   命名空间.sql语句的id    === 类.class.getName()+" ." +id
    * 后面就是要传过去的值
    * */
    @Override
    public Map<String, Object> getMap01ByPk(int skillid) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            System.out.println(Skill.class.getName()+"----com.he.model.Skill");
            //关键步骤
            return sqlSession.selectOne(Skill.class.getName() + ".getMap01ByPk",skillid);
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    @Override
    public Map<String, Object> getMap02ByPk(int skillid) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            return sqlSession.selectOne(Skill.class.getName() + ".getMap02ByPk",skillid);
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    @Override
    public Map<String, Object> getMap03ByPk(int skillid) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            return sqlSession.selectOne(Skill.class.getName() + ".getMap03ByPk",skillid);
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    @Override
    public Skill getSkill01ByPk(int skillid) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            return sqlSession.selectOne(Skill.class.getName() + ".getSkill01ByPk",skillid);
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    @Override
    public Skill getSkill02ByPk(int skillid) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            return sqlSession.selectOne(Skill.class.getName() + ".getSkill02ByPk",skillid);
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }
    @Override
    public List<Map<String, Object>> getSkillList01ByAll() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            return sqlSession.selectList(Skill.class.getName() + ".getSkillList01ByAll");
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

    @Override
    public List<Map<String, Object>> getSkillList02ByAll() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlsession();
            return sqlSession.selectList(Skill.class.getName() + ".getSkillList02ByAll");
        } finally {
            MyBatisUtils.closeSqlSession(sqlSession);
        }
    }

}

9.日志配置文件

log4j.properties

# 日志配置文件Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
# 如果要显示SQL语句,那么这个位置需要配置为命名空间log4j.logger.命名空间
log4j.logger.com.hs.model.Skill=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

10.测试类

MyBatisTest.java

package com.hs.test;
/**
 * 本测试全是采用传统模式:dao层里dao接口写方法,daoImpl实现方法,然后写测试类
 */

import com.hs.dao.SkillDao;
import com.hs.dao.SkillDaoImpl;
import org.junit.Test;

public class MyBatisTest {

    /**
     * 处理结果集为Map类型
     */
    @Test
    public void getMap01ByPk() {
        SkillDao skillDao = new SkillDaoImpl();     //接口回调(个人理解,父类定义变量SkillDao skillDao,子类实例化)
        System.out.println(skillDao.getMap01ByPk(2));
    }

    /**
     * 处理结果集为Map类型—通过给字段取别名方式
     */
    @Test
    public void getMap02ByPk() {
        SkillDao skillDao = new SkillDaoImpl();     //接口回调(个人理解,父类定义变量SkillDao skillDao,子类实例化)
        System.out.println(skillDao.getMap02ByPk(2));
    }

    /**
     * 处理结果集为Map类型—通过resultMap标签处理
     */
    @Test
    public void getMap03ByPk() {
        SkillDao skillDao = new SkillDaoImpl();     //接口回调(个人理解,父类定义变量SkillDao skillDao,子类实例化)
        System.out.println(skillDao.getMap03ByPk(2));
    }

    /**
     * 处理结果集为自定义的类Skill—通过给字段取别名方式
     */
    @Test
    public void getSkill01ByPk() {
        SkillDao skillDao = new SkillDaoImpl();     //接口回调(个人理解,父类定义变量SkillDao skillDao,子类实例化)
        System.out.println(skillDao.getSkill01ByPk(2));
    }

    /**
     * 处理结果集为自定义的类Skill—resultMap标签处理
     */
    @Test
    public void getSkill02ByPk() {
        SkillDao skillDao = new SkillDaoImpl();     //接口回调(个人理解,父类定义变量SkillDao skillDao,子类实例化)
        System.out.println(skillDao.getSkill02ByPk(2));
    }

    /**
     * 处理结果集为集合(list)
     */
    @Test
    public void getSkillList01ByAll() {
        SkillDao skillDao = new SkillDaoImpl();     //接口回调(个人理解,父类定义变量SkillDao skillDao,子类实例化)
        System.out.println(skillDao.getSkillList01ByAll());
    }

    /**
     * 处理结果集为集合(list)—通过resultMap
     */
    @Test
    public void getSkillList02ByAll() {
        SkillDao skillDao = new SkillDaoImpl();     //接口回调(个人理解,父类定义变量SkillDao skillDao,子类实例化)
        System.out.println(skillDao.getSkillList02ByAll());
    }
}

11.在测试类中运行相应的测试

MyBatis学习笔记(二)CRUD操作(查询操作基础)