目录
- 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 configuration
PUBLIC "-//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;
}
@Override
public 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 mapper
PUBLIC "-//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.xml
String resource="mybatis-config.xml";
// 加载文件时,默认到resource目录—->运行后的工作目录classes
InputStream 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注解,表示在执行目标测试方法前,会先执行该方法
@Before
public void init() throws Exception {
//通过 SqlSessionFactory 对象获取一个 SqlSession 会话
sqlsession = MyBatisUtils.getSqlSession();
//获取 MonsterMapper 接口对象, 该对象实现了 MonsterMapper
monsterMapper = sqlsession.getMapper(MonsterMapper.class);
// class com.sun.proxy.$Proxy7动态代理对象
// System.out.println(monsterMapper.getClass());
}
@Test
public void t1(){
System.out.println("t1");
}
@Test
public 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("添加成功");
}
@Test
public void deleteMonster(){
monsterMapper.delMonster(7);
if(sqlsession!=null){
sqlsession.commit();
sqlsession.close();
}
System.out.println("删除成功");
}
@Test
public 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("更新成功");
}
@Test
public void getMonsterById(){
Monster monster= monsterMapper.getMonsterById(8);
System.out.println(monster);
if(sqlsession!=null){
sqlsession.close();
}
System.out.println("通过id查询成功");
}
@Test
public 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;
@Before
public void init() throws Exception {
//通过 SqlSessionFactory 对象获取一个 SqlSession 会话
sqlsession = MyBatisUtils.getSqlSession();
}
@Test
public 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
@Before
public void init() throws Exception {
sqlSession = MyBatisUtils.getSqlSession();
}
@Test
public 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,完成测试
@Test
public 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();
}
}
@Test
public 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 进行测试
@Test
public 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
@Test
public 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();
}
}