目录
- Mybatis
- 1.快速入门
- 2.Mybatis介绍
- 3.Mybatis工作示意图
- 4.MyBatis 快速入门
- 4.1.1创建monster表
- 4.1.2 创建resources/mybatis-config.xml
- 4.1.3 创建pojo类
- 4.1.4 创建MonsterMapper接口
- 4.1.5 创建MonsterMapper.xml
- 4.1.6 mybatis-config.xml 引入Mapper.xml 文件
- 4.1.6 创建SqISession工具类
- 4.1.7 创建测试类
- 5.日志输出-查看 SQL
- 6.原生的 API&注解方法
- 6.MyBatis-注解的方式操作sql
- 6.1 创建MonsterAnnotation接口,添加注解
- 6.2 修改mybatis-config.xml , 对 MonsterAnnotaion 进行注册
- 6.3 添加测试类
- 6.4 org.apache.ibatis.binding.BindingException:
- 6.5 注意事项和说明:
- 7.mybatis-config.xml-配置文件详解
- 7.1 properties 属性
- 7.1 修改 mybatis-confing.xml
- 7.2 setting 属性
- 7.3 typeAliases 别名处理器
- 7.3 environments 环境
- 8. XxxxMapper.xml-SQL 映射文件
- 8.1 XxxMapper.xml-基本介绍
- 8.2 XXxxMapper.xml-详细说明
- 8.2.1 XXxxMapper.xml-传入 POJO 类型
- 8.2.2 XXxxMapper.xml-传入 HashMap
- 8.2.3 XXxxMapper.xml-传入和返回都是HashMap
Mybatis
1.快速入门
2.Mybatis介绍
1.MyBatis 在 java 和 sql 之间提供更灵活的映射方案 2.mybatis 可以将对数据表的操作(sql,方法)等等直接剥离,写到 xml 配置文件,实现和 java代码的解耦 3.mybatis 通过 SQL 操作 DB, 建库建表的工作需要自己完成 |
3.Mybatis工作示意图
4.MyBatis 快速入门
完成对 monster 表的 crud操作
4.1.1创建monster表
CREATE DATABASE `mybatis` CREATE TABLE `monster`
`id` INT NOT NULL AUTO_INCREMENT, `age` INT NOT NULL, `birthday` DATE DEFAULT NULL, `email` VARCHAR(255) NOT NULL , `gender` TINYINT NOT NULL, `name` VARCHAR(255) NOT NULL, `salary` DOUBLE NOT NULL,
PRIMARY KEY (`id`)
) CHARSET=utf8
4.1.2 创建resources/mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--配置mybatis自带的日志输出-查看原生的sql--><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><!--配置别名--><typeAliases><typeAlias type="com.rjh.entity.Monster" alias="Monster"></typeAlias><!--<typeAlias type="com.rjh.entity.Monk" alias="Monk"></typeAlias>--></typeAliases><environments default="development"><environment id="development"><!--配置事务管理器--><transactionManager type="JDBC"/><!--配置数据源--><dataSource type="POOLED"><!--配置连接url--><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/><property name="username" value="root"/><property name="password" value="1111"/></dataSource></environment></environments><mappers><mapper resource="com/rjh/mapper/MonsterMapper.xml"></mapper></mappers>
</configuration>
4.1.3 创建pojo类
package com.rjh.entity;import java.util.Date;//要求这里的实体类属性要和表名字段保持一致
public class Monster {private Integer id;private Integer age;private String name;private String email;private Date birthday;private double salary;private Integer gender;public Monster() {}public Monster(Integer id, Integer age, String name, String email, Date birthday, double salary, Integer gender) {this.id = id;this.age = age;this.name = name;this.email = email;this.birthday = birthday;this.salary = salary;this.gender = gender;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}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 Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public Integer getGender() {return gender;}public void setGender(Integer gender) {this.gender = gender;}@Overridepublic String toString() {return "Monster{" +"id=" + id +", age=" + age +", name='" + name + '\'' +", email='" + email + '\'' +", birthday=" + birthday +", salary=" + salary +", gender=" + gender +'}';}
}
4.1.4 创建MonsterMapper接口
package com.rjh.mapper;import com.rjh.entity.Monster;import java.util.List;//这是一个接口,该接口用于定义操作monster表的方法
//这些方法可以通过注解或者xml文件来实现
public interface MonsterMapper {public void addMonster(Monster monster);public void delMonster(Integer id);public void updateMonster(Monster monster);public Monster getMonsterById(Integer id);// 如果返回为集合,应该设置为集合包含的类型,而不是集合本身的类型public List<Monster> findAllMonster();
}
4.1.5 创建MonsterMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace="com.rjh.mapper.MonsterMapper"说明本 mapper.xml 文件是用来 映射管理 MonsterMapper 接口,主要是去实现 MonsterMapper 接口声明方法namespace指定该xml文件和哪一个接口对应
--><!--select: 实现一个查询操作 insert:表示一个添加操作--><!--id="addMonster" 表示 MonsterMapper 接口 的方法名--><!--resultType="xx" 返回的结果类型,如果没有就不需要写--><!--parameterType="com.rjh.entity.Monster" 表示该方法输入的形参类型,com.rjh.entity.Monster可以简写--><!--(age,birthday,email,gender,name,salary) 表的字段名--><!--#{age},#{birthday},#{email},#{gender},#{name},#{salary} 是实体类 Monster 的属性-->
<mapper namespace="com.rjh.mapper.MonsterMapper"><insert id="addMonster" parameterType="com.rjh.entity.Monster" useGeneratedKeys="true" keyProperty="id">INSERT INTO monster (age,birthday,email,gender,name,salary)VALUES(#{age},#{birthday},#{email},#{gender},#{name},#{salary})</insert><delete id="delMonster" parameterType="java.lang.Integer">delete from monster where id = #{id}</delete><update id="updateMonster" parameterType="Monster">update monster set age=#{age},birthday=#{birthday},email=#{email},gender=#{gender},name=#{name},salary=#{salary} where id=#{id}</update><select id="getMonsterById" parameterType="java.lang.Integer" resultType="Monster">select * from monster where id=#{id};</select><select id="findAllMonster" resultType="Monster">select * from monster;</select></mapper>
4.1.6 mybatis-config.xml 引入Mapper.xml 文件
<mappers><mapper resource="com/rjh/mapper/MonsterMapper.xml"></mapper>
</mappers>
4.1.6 创建SqISession工具类
package com.rjh.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 javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;// 1.获得 SqISession 的实例
// 2.SqlSession 提供了对数据库执行 SQL 命所需的所有方法 3.通过 SqISession 实例来直接执行已映射的 SQL 语句public class MyBatisUtils {private static SqlSessionFactory sqlSessionFactory;static {try {
// 指定资源文件,配置文件mybatis-config.xmlString resource="mybatis-config.xml";
// 加载文件时,默认到resource目录—->运行后的工作目录classesInputStream inputStream= Resources.getResourceAsStream(resource);sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}
// 编写方法:返回sqlsession对象-会话public static SqlSession getSqlSession() {return sqlSessionFactory.openSession();}
}
4.1.7 创建测试类
package com.rjh.mapper;import com.rjh.entity.Monster;
import com.rjh.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Before;
import org.junit.Test;import java.util.Date;
import java.util.List;public class MonsterMapperTest {private SqlSession sqlsession;private MonsterMapper monsterMapper;
// 当方法使用before注解,表示在执行目标测试方法前,会先执行该方法@Beforepublic void init() throws Exception {//通过 SqlSessionFactory 对象获取一个 SqlSession 会话sqlsession = MyBatisUtils.getSqlSession();//获取 MonsterMapper 接口对象, 该对象实现了 MonsterMappermonsterMapper = sqlsession.getMapper(MonsterMapper.class);
// class com.sun.proxy.$Proxy7动态代理对象
// System.out.println(monsterMapper.getClass());}@Testpublic void t1(){System.out.println("t1");}@Testpublic void addMonster(){for(int i=0;i<1;i++){Monster monster=new Monster();monster.setAge(10);monster.setBirthday(new Date());monster.setEmail("123@qq");monster.setGender(0);monster.setName("牛魔王2");monster.setSalary(2000);monsterMapper.addMonster(monster);System.out.println("添加对象"+monster);}
// 如果是增删改,需要提交if(sqlsession!=null){sqlsession.commit();sqlsession.close();}System.out.println("添加成功");}@Testpublic void deleteMonster(){monsterMapper.delMonster(7);if(sqlsession!=null){sqlsession.commit();sqlsession.close();}System.out.println("删除成功");}@Testpublic void updateMonster(){Monster monster=new Monster();monster.setAge(20);monster.setBirthday(new Date());monster.setEmail("234@qq");monster.setGender(1);monster.setName("孙悟");monster.setSalary(200);monster.setId(8);monsterMapper.updateMonster(monster);if(sqlsession!=null){sqlsession.commit();sqlsession.close();}System.out.println("更新成功");}@Testpublic void getMonsterById(){Monster monster= monsterMapper.getMonsterById(8);System.out.println(monster);if(sqlsession!=null){sqlsession.close();}System.out.println("通过id查询成功");}@Testpublic void findAllMonster(){List<Monster> allMonster = monsterMapper.findAllMonster();for (Monster monster : allMonster) {System.out.println(monster);}if(sqlsession!=null){sqlsession.close();}System.out.println("查询成功");}
}
5.日志输出-查看 SQL
在mybatis-config.xml文件里添加下面的语句
<!--配置mybatis自带的日志输出-查看原生的sql--><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings>
6.原生的 API&注解方法
使用 MyBatis 原生的 API 完成,就是直接通过SqlSession 接口的方法来完成
public class sqlsessionTest {private SqlSession sqlsession;@Beforepublic void init() throws Exception {//通过 SqlSessionFactory 对象获取一个 SqlSession 会话sqlsession = MyBatisUtils.getSqlSession();}@Testpublic void myBatisNativeCrud(){Monster monster = new Monster();monster.setAge(200);monster.setBirthday(new Date());monster.setEmail("100@sohu.com");monster.setGender(2);monster.setName("白骨精");monster.setSalary(9234.89);sqlsession.insert("com.rjh.mapper.MonsterMapper.addMonster",monster);if (sqlsession != null) {sqlsession.commit();sqlsession.close();}=======================delete==========================sqlsession.delete("com.rjh.mapper.MonsterMapper.delMonster",12);if (sqlsession != null) {sqlsession.commit();sqlsession.close();}//===========update start======================Monster monster = new Monster();monster.setAge(300);monster.setBirthday(new Date());monster.setEmail("tn100@sohu.com");monster.setGender(2);monster.setName("狮驼国妖精");monster.setSalary(9234.89);monster.setId(7);sqlsession.update("com.hspedu.mapper.MonsterMapper.updateMonster", monster);if (sqlsession != null) {sqlsession.commit();sqlsession.close();}
//===========update end======================//=========select start=================List<Monster> monsterList =sqlsession.selectList("com.rjh.mapper.MonsterMapper.findAllMonster");for (Monster monster1 : monsterList) {System.out.println(monster1);}}
}
6.MyBatis-注解的方式操作sql
6.1 创建MonsterAnnotation接口,添加注解
public interface MonsterAnnotation {@Insert("INSERT INTO monster (age,birthday,email,gender,name,salary) " +"VALUES(#{age},#{birthday},#{email},#{gender},#{name},#{salary}")public void addMonster(Monster monster);@Delete("delete from monster where id=#{id}}")public void delMonster(Integer id);//修改 Monster@Update("UPDATE monster SET age=#{age}, birthday=#{birthday}, "+ "email = #{email},gender= #{gender}, "+ "name=#{name}, salary=#{salary} " + "WHERE id=#{id}")public void updateMonster(Monster monster);//查询-根据 id@Select("SELECT * FROM monster WHERE " + "id = #{id}")public Monster getMonsterById(Integer id);//查询所有的 Monster@Select("SELECT * FROM monster ")public List<Monster> findAllMonster();
}
6.2 修改mybatis-config.xml , 对 MonsterAnnotaion 进行注册
<mappers>
<!-- 这里会引入我们的 Mapper.xml 文件 -->
<mapper resource="com/hspedu/mapper/MonsterMapper.xml"/>
<!--解读
1. 如果是通过注解的方式,可以不使用 MonsterMapper.xml
2. 但是需要在 mybatis-config.xml 注册含注解的类
-->
<mapper class="com.rjh.mapper.MonsterAnnotation"/>
6.3 添加测试类
public class MonsterAnnotationTest {private SqlSession sqlSession;private MonsterAnnotation monsterAnnotation@Beforepublic void init() throws Exception {sqlSession = MyBatisUtils.getSqlSession();}@Testpublic void addMonster() {Monster monster = new Monster();monster.setAge(500);monster.setBirthday(new Date());monster.setEmail("1235@sohu.com");monster.setGender(2);monster.setName("白虎精");monster.setSalary(9234.89);monsterAnnotation = sqlSession.getMapper(MonsterAnnotation.class);monsterAnnotation.addMonster(monster);//增删改,需要提交事务if (sqlSession != null) {sqlSession.commit();sqlSession.close();}System.out.println("操作成功");Monster monsterById = monsterAnnotation.getMonsterById(10);System.out.println(monsterById);}
}
6.4 org.apache.ibatis.binding.BindingException:
sql语句问题或者是config.xml没有导入注解相关配置
6.5 注意事项和说明:
1. 如果是通过注解的方式,就不再使用 MonsterMapper.xml文件 ,但是需要在mybatis-config.xml 文件中注册含注解的类/接口 2.使用注解方式,添加时, 如果要返回自增长id值,可以使用@Option注解,组合使用 |
@Insert("INSERT INTO monster (age,birthday,email,gender,name,salary) VALUES(#{age},#{birthday},#{email},#{gender},#{name},#{salary})")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
public void addMonster(Monster monster);
7.mybatis-config.xml-配置文件详解
mybatis 的核心配置文件(mybatis-config.xml),比如配置 jdbc 连接信息,注册 mapper
等等
7.1 properties 属性
通过该属性可以指定一个外部的 jdbc.properties 文件,引入我们的 jdbc 连接信息
7.1 修改 mybatis-confing.xml
<!-- 这里就是引入 jdbc.properties 文件 -->
<properties resource="jdbc.properties"/>
<environments default="development"><environment id="development"><!--配置事务管理器--><transactionManager type="JDBC"/><!--配置数据源--><dataSource type="POOLED"><!--配置连接url--><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments>
修改父项目的 pom.xml(如果已经配置了.properties 就不用再配置)
7.2 setting 属性
配置mybatis自带的日志输出-查看原生的sql,之前配置过一个
<settings><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
7.3 typeAliases 别名处理器
1. 别名是为 Java 类型命名一个短名字。它只和 XML 配置有关,用来减少类名重复的部分 2. 如果指定了别名,我们的 MappperXxxx.xml 文件就可以做相应的简化处理 3.注意指定别名后,还是可以使用全名的 |
<typeAliases>
<!-- 如果一个包下有很多的类,我们可以直接引入包,这样
该包下面的所有类名,可以直接使用
-->
<package name="com.rjh.entity"/>
<!-- 为某个 mapper 指定一个别名, 下面可以在 XxxxxMapper.xml 做相应简化处理 -->
<!-- <typeAlias type="com.hspedu.entity.Monster" alias="Monster"/> -->
</typeAliases>
7.3 environments 环境
- resource 注册 Mapper 文件: XXXMapper.xml 文件(常用,使用过)
- class:接口注解实现(使用过)
- url:外部路径,使用很少,不推荐,
- package 方式注册 :< package name=“com.rjh.mapper”/> 并测试
<!-- 老韩解读
1. 当一个包下有很多的 Mapper.xml 文件和基于注解实现的接口时,
为了方便,我们可以以包方式进行注册
2. 将下面的所有 xml 文件和注解接口都进行注册
-->
<mappers>
<package name="com.rjh.mapper"/>
</mappers>
8. XxxxMapper.xml-SQL 映射文件
在sql语句中,能在parameterType和resultType因为在xml文件中配置了重命名,所以能写简写
8.1 XxxMapper.xml-基本介绍
1.MyBatis 的真正强大在于它的语句映射(在 XxxMapper.xml 配置), 由于它的异常强大, 如 果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。 MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。 2.SQL 映射文件常用的几个顶级元素(按照应被定义的顺序列出) cache – 该命名空间的缓存配置。 cache-ref – 引用其它命名空间的缓存配置。 resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。 parameterType - 将会传入这条语句的参数的类全限定名或别名 |
8.2 XXxxMapper.xml-详细说明
8.2.1 XXxxMapper.xml-传入 POJO 类型
案例 1:请查询 id = 1 或者 name = ‘白骨精’ 的妖怪
案例 2:请查询 name 中 包含 “牛魔王” 的妖怪
//通过 id 或者名字查询
public List<Monster> findMonsterByNameORId(Monster monster);
//查询名字中含义'精'妖怪
public List<Monster> findMonsterByName(String name);
- 修改 MonsterMapper.xml
<!-- 实现 findMonsterByNameORId --><select id="findMonsterByNameORId" parameterType="Monster" resultType="Monster">select * from monster where id=#{id} or name=#{name};
</select><!-- 看看模糊查询的使用 取值 需要 ${value} 取值--><select id="findMonsterByName" parameterType="String" resultType="Monster">select * from monster where name like "%${name}%"</select>
- 修改 MonsterMapperTest.java,完成测试
@Testpublic void findMonsterByNameORId(){Monster monster=new Monster();monster.setName("白虎精");monster.setId(10);List<Monster> list = monsterMapper.findMonsterByNameORId(monster);for(Monster monster1:list){System.out.println(monster1);}if(sqlsession!=null){sqlsession.close();}}@Testpublic void findMonsterByName(){List<Monster> list = monsterMapper.findMonsterByName("精");for(Monster m:list){System.out.println(m);}if(sqlsession!=null){sqlsession.close();}
8.2.2 XXxxMapper.xml-传入 HashMap
要求:声明一个方法,按传入参数是 HashMap 的方式,查询 id > 10 并且 salary 大于 40
的所有妖怪
- 修改 MonsterMapper.java, 增加方法接口
public List<Monster> findMonsterByIdAndSalary_PrameterHashMap(Map<String, Object> map);
- 修改 MonsterMapper.xml
<select id="findMonsterByIdAndSalary_PrameterHashMap" parameterType="map" resultType="Monster">select * from monster where id> #{id} AND salary > #{salary};
</select>
- 修改 MonsterMapperTest.java 进行测试
@Testpublic void findMonsterByIdAndSalary_PrameterHashMap(){Map<String, Object> map=new HashMap<String,Object>();map.put("id",15);map.put("salary",95);List<Monster> list = monsterMapper.findMonsterByIdAndSalary_PrameterHashMap(map);for(Monster m:list){System.out.println(m);}if(sqlsession!=null){sqlsession.close();}}
8.2.3 XXxxMapper.xml-传入和返回都是HashMap
- 修改 MonsterMapper.java
public List<Map<String,Object>> findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap(Map<String, Object> map);
- 修改 MonsterMapper.xml
<select id="findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap" parameterType="map" resultType="map">select * from monster where id > #{id} AND salary > #{salary};</select>
- 修改 MonsterMapperTest.java
@Testpublic void findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap() {Map<String, Object> map = new HashMap<String, Object>();map.put("id", 10);//条件map.put("salary", 900);List<Map<String, Object>> list = monsterMapper.findMonsterByIdAndSalary_PrameterHashMap_ReturnHashMap(map);for(Map<String,Object> map2:list){for (Map.Entry<String, Object> entry : map2.entrySet()) {System.out.println(entry.getKey() + "--" + entry.getValue());}if (sqlSession != null) {sqlSession.close();}}