本文章为学习文章,根据尚硅谷的SSM框架学习视频所记录学习的文章
MyBatis最初是Apache的一个开源项目iBatis,2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下,iBatis3.x正式更名为MyBatis。代码与2013年11月迁移到Github
iBatis一词来源于"internet"和"abatis"的组合,是一个基于Java的持久层框架.IBatis提供的持久层框架包括SQL Map和Data Access Objects(DAO)
https://github.com/mybatis/mybatis-3/releases
IDE:IntelliJ IDEA 2020.1.1 x64
构造工具:maven3.5.4
MyBatis版本:MyBatis3.5.4
添加依赖
<dependencies>
mybatis
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
测试
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
sql的
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
</dependencies>
习惯上命名为mybatis-config.xml,这个文件名仅仅是建议,并非强制要求。将来整合Spring之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。
核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息
核心配置文件存放的位置是src/main/resources目录下
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="" />
mappers>
configuration>
MyBatis的mapper接口相当于以前的DAO,但是区别在于,mapper仅仅是接口,我们不需要提供实现类。
package com.atguigu.mybatis.mapper;
public interface UserMapper {
int insertUser();
}
相关概念:ORM(Object Relationship Mapping)对象关系映射
Java概念和数据库概念
类=表
属性=字段/列
对象=记录/行
①映射文件1命名规则
表所对应的实体类的类名+Mapper.xml
例如:表t_user,映射的实体类为User,所对应的映射文件为UserMapper.xml
因此一个映射文件对应一个实体类,对应一张表的操作
MyBatis映射文件用于编写SQL,访问以及操作表中的数据
MyBatis映射文件存放的位置是src/main/resources/mappers目录下
②MyBatis中可以面向接口操作数据,要保证两个一致:
a>mapper接口的全类目和映射文件的命名空间(namespace)保持一致
b>mapper接口的方法名和映射文件中编写SQL的标签的id属性保持一致
<?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">
<mapper namespace="...">
<select id="..." resultType="...">
select*from...
</select>
</mapper>
命名空间对应Mapper接口全类名
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">mapper>
语句的id要和类的方法名一致
<insert id="insertUser">
insert into t_user values(null,'admin','123456',23,'男','12345@qq.com')
insert>
一定要将配置文件引入到MyBatis核心配置文件中
<mapper resource="mappers/UserMapper" />
核心配置文件和resource文件同一级所以,如果引用的配置文件有父目录,直接父目录/UserMapper
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">
<insert id="insertUser">
insert into t_user values(null,'admin','123456',23,'男','12345@qq.com')
insert>
mapper>
首先创建POJO类对应数据库的表
创建MyBatis核心配置文件
创建Mapper接口
int insertUser()
创建XML文件,对应我们的Mapper接口
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">
<!--
mapper接口和映射文件要保证两个一致
1.mapper接口的全类名和映射文件的namespace一致
2.mapper接口中的方法名要和映射文件中的sql的id保持一致
-->
<!-- int insertUser(); -->
<insert id="insertUser">
insert into t_user values(null,'admin','123456',23,'男','12345@qq.com')
</insert>
然后在核心配置文件中引入该XML文件
<mappers>
<mapper resource="mappers/UserMapper" />
mappers>
在测试类中首先获取XML文件的输入流
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
获取SQL会话工厂构建对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
获取SQL会话工厂对象
通过build方法创建
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
调用SQL会话工厂对象的openSession()方法来获取SQL会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
通过该方法的getMapper来创建一个类的对象,此处包括了接口
底层会生成一个该接口的实现类,我们直接调用接口的方法即可
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
调用方法并且获取返回值打印
int result = mapper.insertUser();
因为该操作的事务需要手动管理,所以不会提交,为了避免回滚我们需要手动提交一下
sqlSession.commit();
释放会话流资源
sqlSession.close();
空参sqlSessionFactory.openSession();不会自动提交事务
单参sqlSessionFactory.openSession(true);会自动提交事务
添加log4j依赖
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
执行原理
通过反射来获取参数然后封装执行
日志的级别
FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试)
从左到右打印的内容越来越详细
修改和删除用户的功能
封装一个SqlSession对象工厂创建工具类
package com.atguigu.mybatis.utils;
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 SqlsessionUtil {
public static SqlSession getSqlSession() {
SqlSession sqlSession = null;
try {
//获取核心配置文件的输入流
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//获取SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//获取SqlSession对象 填入true 默认事务提交
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException ioException) {
ioException.printStackTrace();
}
return sqlSession;
}
}
首先在UserMapper接口中写入要增加的方法
void updateUser();
void deleteUser();
在MyBatisTest测试类中调用
//获取对象
SqlSession sqlSession = SqlsessionUtil.getSqlSession();
//创建代理
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser();//调用方法
在XML文件配置中添加配置信息如下
<update id="updateUser">
update t_user set username = 'root',password = '123' where id = 3
update>
<delete id="deleteUser">
delete from t_user where id = 3;
delete>
查询一定要在配置文件中指明结果映射,此处需要指明结果映射类型
<select id="getUserById" resultType="com.atguigu.mybatis.pojo.User">
select*from t_user where id = 1
select>
List<User> getAllUser();
<select id="getAllUser" resultType="com.atguigu.mybatis.pojo.User">
select*from t_user;
select>
环境标签
environments:配置数据库连接环境
属性:
default:设置默认使用的环境的id
environment:设置一个具体的连接数据库的环境
属性:
id:设置环境的唯一标识,不能重复
transactionManager:事务管理器
dataSource:数据源
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mappers/UserMapper" />
mappers>
configuration>
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.username=root
jdbc.password=password
typeAliases类型别名
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<typeAliases>
<package name="com.at guigu.mybatis.pojo"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mappers/UserMapper" />
mappers>
configuration>
创建包目录 com/atguigu/mybatis/mapper
我们为了方便mappers标签的引入,将创建和包相匹配的目录
<mappers>
<package name="com.atguigu.mybatis.mapper"/>
</mappers>
自定义模板保存到IDEA中,创建文件时直接使用模板
mybatis-config
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<typeAliases>
<package name=""/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
dataSource>
environment>
environments>
<mappers>
<package name=""/>
mappers>
configuration>
mybatis-mapper
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
mapper>
/*
Mybatis获取参数值的两种方式:#{}和${}
#{}的本质是占位符赋值,${}的本质是字符串拼接
1、若mapper接口方法的参数为单个的字面量类型
此时可以通过#{}和${}以任意的内容获取参数值,一定要注意${}的单引号问题
2、若mapper接口方法的参数为多个字面量类型
此时MyBatis会将参数放在map集合中,以两种方式来存储数据
a>以arg0,arg1,arg2...
b>以param1,param2,param3...
因此只需要通过#{}和${}来访问map集合的键,就可以来获取相对应的值
一定要注意${}的单引号问题
3、若mapper接口的方法参数为一个map集合类型的参数
只需要通过#{}和${}来访问map集合的键,就可以来获取相对应的值
4、若mapper接口的方法参数为实体类类型的参数
只需要通过#{}和${}来访问实体类中的属性名,就可以获取相对应的属性值
5、可以在mapper接口方法的参数上设置@Param注解
此时将MyBatis会将这些参数放在map中,以两种方式进行存储
a>以@Param注解的value属性值为键,以参数值
b>以param1,param2...为键,以参数为值
只需要通过#{}和${}来访问实体类中的属性名,就可以获取相对应的属性值
*/
${}:拼接字符串形式
#{}:占位符形式
select*from t_user where username = '${username}'
也可以自定义键
SqlSession sqlSession = SqlsessionUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<>();
map.put("username","admin");
map.put("password","123456");
User user = mapper.checkLoginByMap(map);
System.out.println("user = " + user);
SqlSession sqlSession = SqlsessionUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(null,"root","123456",33,"女","123@qq.com");
mapper.insertUser(user);
<select id="checkLoginByMap" resultType="User">
select * from t_user where username = #{username} and password = #{password}
select>
<select id="insertUser">
insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email})
select>
@Test
public void testGetAllUserToMap(){
SqlSession sqlSession = SqlsessionUtil.getSqlSession();
SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
// List
若查询的数据有多条时,并且要将每条数据转换为我们的Map集合,此时有两种解决方案:
1、将Mapper接口方法的返回值设置为泛型是Map的List集合
2、可以将每条数据转换成的Map集合放在一个大的Map集合中,但是必须要通过@MapKey注解,来讲查询的某个字段的值作为大的Map的键 此处为@MapKey(“id”)
如果我们想要进行一个模糊查询,则普通的SQL语句无法完成该操作
try {
Class.forName("");
Connection connection = DriverManager.getConnection("","","");
String sql = "select*from t_user where username like '%?%'";
PreparedStatement ps = connection.prepareStatement(sql);
//ps.setString(1,"a");
} catch (Exception e) {
e.printStackTrace();
}
String sql = "select*from t_user where username like '%?%'";
这句代码我们在IDEA中
如果填充占位符会直接编译报错
因为此处的占位符被当成了字符串的一部分
所以我们的Mapper映射文件也是如此
<select id="getUserByLike" resultType="User">
select*from t_user where username like '%#{mohu}%';
select>
解决方案:三种
第一种
第一种解决方法将占位符直接写死
<select id="getUserByLike" resultType="User">
select*from t_user where username like '%a%';
select>
第二种
<select id="getUserByLike" resultType="User">
select*from t_user where username like concat('%'#{mohu}m,'%');
select>
第三种
<select id="getUserByLike" resultType="User">
select * from t_user where username like "%"#{mohu}"%"
select>
批量查询
此处要进行批量操作,但是如果仅仅是#{ids}
拼接时将会携带’',变成字符串形式,导致报错,此处需要使用${}形式来进行SQL语句执行
<select id="deleteMoreUser">
delete from t_user where id in(${ids});
select>
我们将表名设置为一个动态的参数,通过动态参数来赋值给SQL语句来达到动态的查询方式
<select id="getUserList" resultType="User">
该方式会将tableName变成占位符
select*from #{tableName}
下面的形式才是正确的拼接方式
select*from ${tableName}
select>
在原生的JDBC中如果想要调用的话需要打开属性,输入1或者常量
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email});
insert>