1.MyBatis介绍
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plan Old Java Objects,普通的 Java 对象)映射成数据库中的记录。
2.MyBatis入门程序
2.0 项目结构
2.1导入maven依赖
<dependencies>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!-- MySQL 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>
2.2编写配置文件
<?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">
<!--将有关MyBatis有关的配置都放在configuration标签中-->
<configuration>
<!--
开发环境 ===== A
测试环境 ===== B
生产环境 ===== C
default="" 使用哪个环境
default的值和那个id对应使用的就是哪个环境
-->
<environments default="dev">
<environment id="dev">
<!--事务管理器 帮我们管理事务-->
<transactionManager type="JDBC"></transactionManager>
<!--数据库连接池获取连接-->
<dataSource type="POOLED">
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/409ssm?characterEncoding=utf8&useSSL=false&serverTimezone=UTC"/>
</dataSource>
</environment>
</environments>
</configuration>
2.3 创建接口
public interface UserDao {
//获取数据库中User表中数据的总量
// select count(1) from user
public int getCount();
}
2.4 编写映射文件
<?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="buka.dao.UserDao">
<!--select: 查询 id:指定接口的方法名
resultType:设置方法的返回值类型
-->
<select id="getCount" resultType="int">
<!--编写具体的sql语句-->
select count(1) from `user`
</select>
</mapper>
2.5 映射文件保存进配置文件中
<!--写入我们的映射文件-->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
2.6 测试
import buka.dao.UserDao;
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.Reader;
public class MyBatisTest {
public static void main(String[] args) throws IOException {
String resource = "mybatisConfig.xml";
Reader reader = Resources.getResourceAsReader(resource);
//获取SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 获取一次SQL会话 SqlSession
SqlSession session = sqlSessionFactory.openSession();
// 获取数量 参数为UserDao接口 获取到UserDao类型的对象
// 获取接口的代理对象org.apache.ibatis.binding.MapperProxy@68be2bc2
UserDao userDao = session.getMapper(UserDao.class);
System.out.println(userDao.getCount());
}
}
测试结果: 显示6条数据
3.SQL映射文件编写
3.1编写接口
public interface UserDao {
//获取数据库中User表中数据的总量
// select count(1) from user
public int getCount();
// insert 返回值代表受影响的行数
public int addUser();
public boolean delUser();
public boolean updateUser();
}
3.2编写映射文件编写映射文件
3.2.1插入
<!--插入数据 id:指定方法的名字
没有返回值类型 没有resultType属性
-->
<insert id="addUser">
INSERT INTO `user`(userName) VALUE ('MyBatis');
</insert>
3.2.1删除
<!--删除数据 id:指定名字
没有resultType属性
当返回值时boolean类型时 如果受影响的行数!=0 返回true
如果受影响的行数=0 说明操作没有成功 返回false
-->
<delete id="delUser">
DELETE FROM `user` WHERE id = 1
</delete>
3.2.1更新
<!--更新数据 id:方法的名字 没有resultType属性 -->
<update id="updateUser">
UPDATE `user` SET userName='buka' WHERE id = 16;
</update>
3.2.1查询
<!--select: 查询 id:指定接口的方法名
resultType:设置方法的返回值类型
-->
<select id="getCount" resultType="int">
<!--编写具体的sql语句-->
select count(1) from `user`
</select>
3.3测试
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.Reader;
public class MyBatisTest {
public static void main(String[] args) throws IOException {
String resource = "mybatisConfig.xml";
Reader reader = Resources.getResourceAsReader(resource);
//获取SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 获取一次SQL会话 SqlSession 传入true 代表自动提交事务
SqlSession session = sqlSessionFactory.openSession(true);
// 获取数量 参数为UserDao接口 获取到UserDao类型的对象
// 获取接口的代理对象org.apache.ibatis.binding.MapperProxy@68be2bc2
UserDao userDao = session.getMapper(UserDao.class);
// System.out.println(userDao.getCount());
// int res = userDao.addUser();
//Mybatis 在insert update delete 默认不自动提交事务 需要自己设定自动提交事务
// System.out.println(res);
// boolean res = userDao.delUser();
// System.out.println(res);
System.out.println(userDao.updateUser());
}
}
4.参数传递
4.1传递单个参数
在传递参数时,映射文件中,通过#{参数名}的形式获取参数值
接口方法
public interface UserDao {
//传递单个参数 映射文件中 #{参数名}
public int selectCount(String userName);
}
映射文件
<select id="selectCount" resultType="int">
select count(1) from `user` where userName=#{userName}
</select>
4.2 传递多个参数
在传递多个参数时,在映射文件中,通过#{参数名}的形式无法获取参数值,会出现异常
接口方法
public interface UserDao {
public int selectCountByNameAndId( String userName, int id);
}
映射文件
<select id="selectCount" resultType="int">
select count(1) from `user` where userName=#{userName} and id=#{id}
</select>
出现参数绑定异常
此时使用#{param1}、#{param2}...或者#{arg0}、#{arg1}...的形式获取对应的位置的参数值
映射文件
<select id="selectCountByNameAndId" resultType="int">
select count(1) from `user`where userName=#{param1}and id=#{param2}
</select>
此时测试没有问题
在参数的前面加上注解@Param 其中注解的参数是给方法的中的参数起别名,在映射文件中#{别名}获取参数值
接口方法:
public int selectCountByNameAndId( @Param("userName") String userName, @Param("a") int id);
映射文件
<select id="selectCountByNameAndId" resultType="int">
select count(1) from `user`where userName=#{userName}and id=#{a}
</select>
测试如下,sql语句也能正确执行
4.3传递javaBean
在接口方法中,以javaBean类型为参数类型时,在映射文件中,可以通过#{属性名}获取对象的中的属性值
JavaBean
ublic class User {
private String name;
private String pwd;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public User(String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
public User() {
}
}
接口方法
public boolean addUserByJavaBean(User user);
映射文件
<insert id="addUserByJavaBean">
insert into `user`(userName,userPwd) value (#{name},#{pwd})
</insert>
测试结果如下:
4.4 传递Map集合
在接口方法中,以Map类型为参数类型时,在映射文件中,可以通过#{key}获取参数Map中的value的值
接口方法
public boolean updateUserByMap(Map<String,Object> map);
映射文件
<update id="updateUserByMap">
update `user` set userName=#{userName} where id =#{id}
</update>
测试方法
Map<String,Object> map = new HashMap<>();
map.put("userName","456789");
map.put("id",9);
boolean res = userDao.updateUserByMap(map);
System.out.println(res);
测试结果如下:
更新成功
4.5 复杂类型传参
在接口中,即存在Map类型又存在JavaBean类型,在Mapper映射文件中如何获取参数值
接口方法
public boolean deleteUser(Map<String,String> map,User user);
映射文件:通过#{param1.key}获取map参数中的value值,通过#{param2.属性名}获取javaBean的属性值
<delete id="deleteUser">
delete from `user` where userName=#{param1.userName} and userPwd=#{param2.pwd}
</delete>
同时,也给每个参数取别名,通过#{别名.key}以及#{别名.属性名}分别获取map的value值以及javaBean的属性值,案例如下
接口方法
public boolean deleteUser(@Param("m") Map<String,String> map,@Param("u") User user);
映射文件:通过#{param1.key}获取map参数中的value值,通过#{param2.属性名}获取javaBean的属性值
<delete id="deleteUser">
delete from `user` where userName=#{m.userName} and userPwd=#u.pwd}
</delete>
测试成功,可以删除数据,返回true
Map<String,String> map = new HashMap<>();
map.put("userName","java");
User user = new User("","buka");
boolean res = userDao.deleteUser(map,user);
System.out.println(res);