MyBatis是一款优秀的持久层框架,用于简化JDBC开发。
MyBatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql中的动态参数进行映射生成最终执行的SQL语句。
最后MyBatis框架执行SQL并将结果集映射为java对象并返回。采用ORM思想(对象关系映射)解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。
持久层
框架
实例:查询user表中的所有数据
创建user表,添加数据
create database mybatis;
use mybatis;
drop table if exists tb_user;
create table tb_user(
id int primary key auto_increment,
username varchar(20),
password varchar(20),
gender char(1),
addr varchar(30)
);
INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');
创建模块mybatis-demo,导入坐标
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>mybatis-demoartifactId>
<version>1.0-SNAPSHOTversion>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.5version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.32version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.20version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.2.3version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-coreartifactId>
<version>1.2.3version>
dependency>
dependencies>
project>
project>
编写MyBatis核心配置文件 → 替换连接信息,解决硬编码问题
配置文件mybatis-config.xml
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.itheima.pojo"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
dataSource>
environment>
environments>
<mappers>
<package name="com.itheima.mapper"/>
mappers>
configuration>
编写SQL映射文件 → 统一管理SQL语句,解决硬编码问题
SQL映射文件UserMapper.xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.UserMapper">
<select id="selectAll" resultType="user">
select * from tb_user;
select>
<select id="selectById" resultType="user">
select * from tb_user where id = #{id};
select>
mapper>
编码
定义POJO类
public class User {
private Integer id;
private String username;
private String password;
private String gender;
private String addr;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", gender='" + gender + '\'' +
", addr='" + addr + '\'' +
'}';
}
}
加载核心配置文件,获取SQLSessionFactory对象
获取SQLSession对象,执行SQL语句
释放资源
import com.itheima.pojo.User;
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;
import java.util.List;
/**
* Mybatis 快速入门代码
*/
public class MyBatisDemo {
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 执行sql
List<User> users = sqlSession.selectList("com.itheima.mapper.UserMapper.selectAll");
System.out.println(users);
//4. 释放资源
sqlSession.close();
}
}
解决SQL映射文件的警告提示
目的:解决原生方式中的硬编码,简化后期执行SQL
定义与SQL映射文件同名的mapper接口,并且将mapper接口和SQL映射文件放置在同一目录下。(在resource下创建包使用/来分割每层而不能使用.分割)
设置SQL映射文件的namespace属性为mapper接口全限定名,即com.itheima.mapper.UserMappe
在mapper接口中定义方法,方法名就是SQL映射文件中SQL语句的id,并保持参数类型和返回值类型一致
UserMapper.java
package com.itheima.mapper;
import com.itheima.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface UserMapper {
// 方法名要与UserMapper.xml中的SQL语句的id一致
// 返回值类型与SQL语句中的resultType一致
List<User> selectAll();
User selectById(int id);
}
编码
注意:如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载。
package com.itheima;
import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
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;
import java.util.List;
/**
* Mybatis 代理开发
*/
public class MyBatisDemo2 {
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAll();
System.out.println(users);
//4. 释放资源
sqlSession.close();
}
}
mybatis核心配置文件的顶层结构如下:
注意:配置各个标签时,需要遵守前后顺序
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.itheima.pojo"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<package name="com.itheima.mapper"/>
mappers>
configuration>
无论是MyBatis在预处理语句(PrepareStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成Java类型,下面是部分默认的类型处理器:
可以重写类型处理器或创建自己的类型处理器来处理不支持的或非标准的类型,具体做法为:实现TypeHandler接口,或继承BaseTypeHandler,然后可以选择性地将它映射到一个JDBC类型。
例如:一个Java中的Date数据类型,我们想将它存到数据库的时候存成一个1970年至今的毫秒数,取出来时转换成Java的Date,即Java的Date和数据库的varchar毫秒值之间转换。
开发步骤:
示例:自定义DateTypeHandler类型处理器
public class DateTypeHandler extends BaseTypeHandler<Date>{
// 将Java类型转换成数据库需要的类型
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType){
long time = date.getTime(); // 将date转为毫秒值
preparedStatement.setLong(i, time);
}
// 将数据库中的类型转换成Java类型
// String参数:要转换的字段的名称
// ResultSet:查询出的结果集
public Date getNullableResult(ResultSet resultSet, String s) throws SQLException{
// 获取结果中需要的数据(long)转换成Date类型并返回
long aLong = reaultSet.getLong(s);
Date date = new Date(aLong);
return date;
}
// 将数据库中的类型转换成Java类型
public Date getNullableResult(ResultSet resultSet, int i) throws SQLException{
// 参数i表示的是字段在结果集中的位置
long aLong = reaultSet.getLong(i);
Date date = new Date(aLong);
return date;
}
// 将数据库中的类型转换成Java类型
public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException{
long aLong = callableStatement.getLong(s);
Date date = new Date(aLong);
return date;
}
}
在mybatis-config.xml中注册类型处理器
<typeHandlers>
<typeHandler handler="com.itheima.handler.DateTypeHandler">typeHandler>
typeHandlers>
MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据:
开发步骤:
示例:
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>paghelperartifactId>
<version>3.7.5version>
dependency>
<dependency>
<groupId>com.github.jsqlparsergroupId>
<artifactId>jsqlparserartifactId>
<version>0.9.1version>
dependency>
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql">property>
plugin>
plugins>
package com.itheima;
import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
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;
import java.util.List;
public class PageHelperTest {
public static void main(String[] args) throws IOException {
//1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 设置分页相关参数:当前页 + 每页显示的条数
PageHelper.startPage(2,3);
List<User> users = userMapper.selectAll();
for(User user : users){
System.out.println(user);
}
// 获得与分页相关参数
PageInfo<User> pageInfo = new PageInfo<User>(users);
System.out.println("当前页:" + pageInfo.getPageNum());
System.out.println("每页显示条数:" + pageInfo.getPageSize());
System.out.println("总条数:" + pageInfo.getTotal());
System.out.println("总页数:" + pageInfo.getPages());
System.out.println("上一页:" + pageInfo.getPrePage());
System.out.println("下一页:" + pageInfo.getNextPage());
System.out.println("是否是第一页:" + pageInfo.isFirstPage());
System.out.println("是否是最后一页:" + pageInfo.isLastPage());
//4. 释放资源
sqlSession.close();
}
}
MyBatisX插件
编写接口方法:Mapper接口
List<Brand> selectAll();
编写SQL语句:SQL映射文件
<select id="selectAll" resultType="brand">
select
id,
brand_name as brandName,
company_name as companyName,
ordered,
description,
status
from tb_brand;
select>
<sql id="brand_column">
id,
brand_name as brandName,
company_name as companyName,
ordered,
description,
status
sql>
<select id="selectAll" resultType="brand">
select
<include refid="brand_column"/>
from tb_brand;
select>
<realutMap id="brandResultMap" type="brand">
<result column="brand_name" property="brandName"/>
<result column="company_name" property="companydName"/>
realutMap>
<select id="selectAll" resultMap="brandResultMap">
select *from tb_brand;
select>
执行方法,测试
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testSelectAll() throws IOException {
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
List<Brand> brands = brandMapper.selectAll();
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
}
编写接口方法:Mapper接口
Brand selectById(int id);
编写SQL语句:SQL映射文件
<select id="selectById" parameterType="int" resultMap="brandResultMap">
select *from tb_brand where id = #{id};
select>
执行方法,测试
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testSelectById() throws IOException {
//接收参数
int id = 1;
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
Brand brand = brandMapper.selectById(id);
System.out.println(brand);
//5. 释放资源
sqlSession.close();
}
}
多条件查询
编写接口方法
/*
mybatis 提供了三种不同的参数接收方式:
1.散装参数
需要使用@Param("SQL参数占位符名称")
例如SQL参数占位符#{status}的名称就是status
2.实体类封装参数
可以直接将其封装为一个对象来传递,#{status}时会自动找到对象的get方法获取参数值。
因此参数占位符的名称要和实体类的属性名一致,否则无法找到对应的get方法
3.map集合
要保证map集合的键的名称和SQL语句中的参数占位符的名称保持一致
*/
List<Brand> selectByCondition(@Param("status")int status, @param("companyName") String companyName, @param("brandName") String brandName);
List<Brand> selectByCondition(Brand brand);
List<Brand> selectByCondition(Map map);
编写SQL语句:SQL映射文件
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
where
status = #{status}
and company_name like #{companyName}
and brand_naem like #{brandName};
select>
以上这种写法在程序运行时存在bug,例如:如果第三个参数的值是null,那么用户将查询不出结果。因为按照之前的代码,查询的是三个参数条件都满足的记录,此时编译后的SQL语句是
select * form tb_brand where status = ? and company_name = ? and brand_name = ?
而SQL语句会随着用户的输入或者外部条件的变化而变化,我们称为动态SQL。
mybatis对动态SQL有很强大的支撑:
if:条件判断
属性:test = “逻辑表达式”
问题:如果第一个
select * from tr_brand where and company_name = ?
**解决方式1:**在where后面写一个恒等式,比如1=1,则编译后的SQL语句为
select * from tr_brand where 1 = 1 and company_name = ?
解决方式2:
choose(when, otherwise)
trim(where, set)
foreach:循环遍历
sql:sql片段抽取
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
where
<if test="status != null">
status = #{status}
if>
<if test="companyName != null and companyName != '' ">
and company_name like #{companyName}
if>
<if test="brandName != null and brandName != '' ">
and brand_naem like #{brandName}
if>
select>
执行方法,测试
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testSelectByCondition() throws IOException {
//接收参数
int status = 1;
String companyName = "华为";
String brandName = "华为";
// 处理参数
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//封装对象
/* Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);*/
Map map = new HashMap();
map.put("status" , status);
map.put("companyName", companyName);
map.put("brandName" , brandName);
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
//List brands = brandMapper.selectByCondition(status, companyName, brandName);
//List brands = brandMapper.selectByCondition(brand);
List<Brand> brands = brandMapper.selectByCondition(map);
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
}
编写接口方法
参数:查询条件
结果:List
List<Brand> selectByConditionSingle(Brand brand);
编写SQL语句:SQL映射文件
从多个条件中选择一个使用choose(when, otherwise):选择,类似于Java中的switch语句
<select id="selectByConditionSingle" resultMap="brandResultMap">
select *
from tb_brand
<where>
<choose>
<when test="status != null">
status = #{status}
when>
<when test="companyName != null and companyName != '' ">
company_name like #{companyName}
when>
<when test="brandName != null and brandName != ''">
brand_name like #{brandName}
when>
choose>
where>
select>
执行方法,测试
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testSelectByConditionSingle() throws IOException {
//接收参数
int status = 1;
String companyName = "华为";
String brandName = "华为";
// 处理参数
companyName = "%" + companyName + "%";
brandName = "%" + brandName + "%";
//封装对象
Brand brand = new Brand();
//brand.setStatus(status);
brand.setCompanyName(companyName);
//brand.setBrandName(brandName);
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
List<Brand> brands = brandMapper.selectByConditionSingle(brand);
System.out.println(brands);
//5. 释放资源
sqlSession.close();
}
}
编写接口方法:Mapper接口
void add(Brand brand);
编写SQL语句:SQL映射文件
<insert id="add">
insert into tb_brand(brnad_name, company_name, ordered, description, status) values(#{brandName}, #{companyName}, #{oedered}, #{description}, #{status});
insert>
执行方法,测试
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testAdd() throws IOException {
//接收参数
int status = 1;
String companyName = "波导手机";
String brandName = "波导";
String description = "手机中的战斗机";
int ordered = 100;
//封装对象
Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);
brand.setDescription(description);
brand.setOrdered(ordered);
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象,openSession是默认开始事务的,即需要手动提交事务
SqlSession sqlSession = sqlSessionFactory.openSession();
//设置openSession()的参数为true表示自动提交事务,即关闭事务
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
brandMapper.add(brand);
//提交事务
sqlSession.commit();
//5. 释放资源
sqlSession.close();
}
}
在数据添加成功后,需要获取插入数据库数据的主键。比如:
<insert id="addOrder" useGenerateKeys="true" keyProperty="id">
insert into tb_order(payment, payment_type, status) values(#{payment}, #{paymentType}, #{status});
insert>
<insert id="addOrderItem">
insert into tb_order_item(goods_name, goods_price, price_count, order_id) values(#{goodsName}, #{goodsPrice}, #{count}, #{orderId});
insert>
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testAdd2() throws IOException {
//接收参数
int status = 1;
String companyName = "波导手机";
String brandName = "波导";
String description = "手机中的战斗机";
int ordered = 100;
//封装对象
Brand brand = new Brand();
brand.setStatus(status);
brand.setCompanyName(companyName);
brand.setBrandName(brandName);
brand.setDescription(description);
brand.setOrdered(ordered);
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
brandMapper.add(brand);
// 获取brand插入数据库后自动生成的id
Integer id = brand.getId();
System.out.println(id);
//提交事务
sqlSession.commit();
//5. 释放资源
sqlSession.close();
}
}
编写接口方法:Mapper接口
void update(Brand brand);
编写SQL语句:SQL映射文件
<update id="update">
update tb_brand
set brand_name = #{brandName},
company_name = #{companyName},
ordered = #{ordered},
description = #{description},
status = #{status}
where id = #{id};
update>
执行方法,测试
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testUpdate() throws IOException {
//接收参数
int status = 0;
String companyName = "波导手机";
String brandName = "波导";
String description = "波导手机,手机中的战斗机";
int ordered = 200;
int id = 6;
//封装对象
Brand brand = new Brand();
brand.setStatus(status);
// brand.setCompanyName(companyName);
// brand.setBrandName(brandName);
// brand.setDescription(description);
// brand.setOrdered(ordered);
brand.setId(id);
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
int count = brandMapper.update(brand);
System.out.println(count);
//提交事务
sqlSession.commit();
//5. 释放资源
sqlSession.close();
}
}
编写接口方法:Mapper接口
编写SQL语句:SQL映射文件
<update id="update">
update tb_brand
<set>
<if test="brandName != null and brandName != ''">
brand_name = #{brandName},
if>
<if test="companyName != null and companyName != ''">
company_name = #{companyName},
if>
<if test="ordered != null">
ordered = #{ordered},
if>
<if test="description != null and description != ''">
description = #{description},
if>
<if test="status != null">
status = #{status}
if>
set>
where id = #{id};
update>
执行方法,测试
编写接口方法:Mapper接口
void deleteById(int id);
编写SQL语句:SQL映射文件
<delete id="deleteById">
delete from tb_brand where id = #{id};
delete>
执行方法,测试
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testDeleteById() throws IOException {
//接收参数
int id = 6;
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
brandMapper.deleteById(id);
//提交事务
sqlSession.commit();
//5. 释放资源
sqlSession.close();
}
}
编写接口方法:Mapper接口
void deleteByIds(@Param(ids)int[] ids);
编写SQL语句:SQL映射文件
<delete id="deleteByIds">
delete from tb_brand where id in (?,?,?)
delete>
<delete id="deleteByIds">
delete from tb_brand where id
in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
foreach>
;
delete>
执行方法,测试
package com.itheima.test;
import com.itheima.mapper.BrandMapper;
import com.itheima.pojo.Brand;
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.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyBatisTest {
@Test
public void testDeleteByIds() throws IOException {
//接收参数
int[] ids = {5,7,8};
//1. 获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2. 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//3. 获取Mapper接口的代理对象
BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//4. 执行方法
brandMapper.deleteByIds(ids);
//提交事务
sqlSession.commit();
//5. 释放资源
sqlSession.close();
}
}
MyBatis接口方法中可以接受各种各样的参数,MyBatis底层对于这些参数进行不同的封装处理方式。MyBatis提供了 ParamNameResolver 类来进行参数封装。
POJO类型:直接使用,属性名 和 参数占位符 一致
Map集合:直接使用,键名 和 参数占位符 一致
Collection:封装为Map集合,键名为 “arg0” 、“connection“
map.put(“arg0”, collection集合);
map.put(“conllection”, collection集合);
List:封装为Map集合,键名为 “arg0” 、“connection”和“list”
map.put(“arg0”, list集合);
map.put(“conllection”, list集合);
map.put(“list”, list集合);
Array:封装为Map集合,键名为 “arg0” 和 “array”
map.put(“arg0”, 数组);
map.put(“array”, 数组);
其他类型:比如int类型,直接使用,参数占位符名称叫什么都无所谓
注意:默认我们都使用@Param注解,替换Map集合中默认的arg键名(只会修改arg为自定义,不会修改其他键名)
对于多个参数传递,MyBatis会将其封装成Map集合,默认方式为
map.put("arg0",参数值1);
map.put("param1",参数值1);
map.put("arg1",参数值2);
map.put("param2",参数值2);
如果在Mapper接口方法传递参数时,没有使用@Param注解定义键的名称,则对应的SQL语句参数占位符名称只能写”arg0“,”arg1“或者”param1“,”param2“。但是不推荐使用这种方式,代码的可读性太差。
// 使用@Param注解来定义参数名称,该名称要和SQL语句中的参数占位符的名称一致。
User select(@Param("username")String username, @Param("password")String password);
若使用了@Param(“username”)注解定义键的名称,则会将”arg0“替换成自定义的参数名,此时SQL语句参数占位符名称可以使用”username“或者”param1“。
使用注解开发会比配置文件开发更加方便
提示:注解完成简单功能,配置文件完成复杂功能
@Select("select *from tb_user where id = #{id}")
public User selectById(int id);
示例:
常用API:SqlSessionFactory build(InputStream inputStream)
通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
String resource = "org/mybatis/builder/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
其中,Resource工具类,这个类在org.apache.ibatis.io包中。Resource类帮助你从类路径下、文件系统或一个web URL中加载资源文件。
SqlSessionFactory有多个方法创建SqlSession实例,常用的有如下两个:
SqlSession实例在MyBatis中是一个非常强大的类,在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法。执行语句的方法主要有:
<T> T selectOne(String statement, Object parameter);
<E> List<E> selectList(String statement, Object parameter);
int insert(String statement, Object parameter);
int update(String statement, Object parameter);
int delete(String statement, Object parameter);
操作事务的方法主要有:
void commit();
void rollback();
手动对Dao进行实现
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由MyBatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类的方法。
Mapper接口开发需要遵循以下规范:
// 代理方式对Dao进行实现
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
<resultMap id="orderMap" type="order">
<id column="oid" property="id">id>
<result column="ordertime" property="ordertime">result>
<result column="total" property="total">result>
<association property="user" javaType="User">
<id column="uid" property="id">id>
<result column="username" property="username">result>
<result column="password" property="password">result>
<result column="birthday" property="birthday">result>
association>
resultMap>
<select id="findAll" resultMap="orderMap">
select *,o.id oid from orders o,user u where o.uid = u.id;
select>
<resultMap id="userMap" type="order">
<id column="uid" property="id">id>
<result column="username" property="username">result>
<result column="password" property="password">result>
<result column="birthday" property="birthday">result>
<collection property="orderList" ofType="Order">
<id column="oid" property="id">id>
<result column="ordertime" property="ordertime">result>
<result column="total" property="total">result>
collection>
resultMap>
<select id="findAll" resultMap="userMap">
select *,o.id oid from user u, orders o where u.id=o.id;
select>
<resultMap id="userRoleMap" type="order">
<id column="uid" property="id">id>
<result column="username" property="username">result>
<result column="password" property="password">result>
<result column="birthday" property="birthday">result>
<collection property="roleList" ofType="Role">
<id column="role_id" property="id">id>
<result column="role_name" property="roleName">result>
<result column="role_desc" property="roleDesc">result>
collection>
resultMap>
<select id="findUserAndRoleAll" resultMap="userRoleMap">
select * from user u, sys_user_role ur, sys_role r where u.id = ur.user_id and ur.role_id = r.id;
select>