MyBatis学习笔记(二)CRUD操作(查询操作基础)
程序员文章站
2022-05-23 19:49:59
...
首发于我的博客 和尚的博客
本篇主要讲解查询操作的结果集处理、映射文件里命名空间设置,SQL语句中resultMap,resultType等属性意思、MyBatis的传统和接口代理模式。
源码获取github
1.整体结构目录
- 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());
}
}