MyBatis(详)
Posted 364.99°
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis(详)相关的知识,希望对你有一定的参考价值。
1. 简介
特性
- 支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架
- 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集
- 可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java
Objects,普通的Java对象)映射成数据库中的记录 - 是一个 半自动的ORM(Object Relation Mapping)框架
和其它持久化层技术对比
- JDBC
- SQL 夹杂在Java代码中耦合度高,导致硬编码内伤
- 维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见
- 代码冗长,开发效率低
- Hibernate 和 JPA
- 操作简便,开发效率高
- 程序中的长难复杂 SQL 需要绕过框架
- 内部自动生产的 SQL,不容易做特殊优化
- 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难
- 反射操作太多,导致数据库性能下降
- MyBatis
- 轻量级,性能出色
- SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
- 开发效率稍逊于HIbernate,但是完全能够接受
2. 搭建
1. 依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
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">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="$driver"/>
<property name="url" value="$url"/>
<property name="username" value="$username"/>
<property name="password" value="$password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
3. 映射文件
<?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="org.mybatis.example.BlogMapper">
<insert id="insertUser">
insert into t_user values(null,'admin','123456',23,'男','12345@qq.com')
</select>
</mapper>
3. mapper接口
public interface UserMapper
int insertUser();
4. 测试
//读取MyBatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//创建SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
//SqlSession sqlSession = sqlSessionFactory.openSession();
//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//通过代理模式创建UserMapper接口的代理实现类对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配 映射文件中的SQL标签,并执行标签中的SQL语句
int result = userMapper.insertUser();
//sqlSession.commit();
System.out.println("结果:"+result);
SqlSession
代表Java程序和数据库之间的会话。(HttpSession是Java程序和浏览器之间的会话)SqlSessionFactory
“生产” SqlSession的 “工厂”
3. 核心配置文件详解
<?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核心配置文件中,标签的顺序:
properties?,settings?,typeAliases?,typeHandlers?, objectFactory?,
objectWrapperFactory?,reflectorFactory?,
plugins?,environments?,databaseIdProvider?,mappers?
-->
<!--引入properties文件-->
<properties resource="jdbc.properties" />
<!--设置类型别名-->
<typeAliases>
<!--typeAlias:设置某个类型的别名
属性:
type:设置需要设置别名的类型
alias:设置某个类型的别名,若不设置该属性,那么该类型拥有默认的别名,即类名 且不区分大小写
-->
<!--<typeAlias type="com.atguigu.mybatis.pojo.User"></typeAlias>-->
<!--以包为单位,将包下所有的类型设置默认的类型别名,即类名且不区分大小写-->
<package name="com.atguigu.mybatis.pojo"/>
</typeAliases>
<!--environments:配置多个连接数据库的环境
属性:
default:设置默认使用的环境的id
-->
<environments default="development">
<!--environment:配置某个具体的环境
属性:
id:表示连接数据库的环境的唯一标识,不能重复
-->
<environment id="development">
<!--transactionManager:设置事务管理方式
属性:
type="JDBC|MANAGED"
JDBC:表示当前环境中,执行SQL时,使用的是JDBC中原生的事务管理方式,事务的提交或回滚需要手动处理
MANAGED:被管理,例如Spring
-->
<transactionManager type="JDBC"/>
<!--dataSource:配置数据源
属性:
type:设置数据源的类型 type="POOLED|UNPOOLED|JNDI"
POOLED:表示使用数据库连接池缓存数据库连接
UNPOOLED:表示不使用数据库连接池
JNDI:表示使用上下文中的数据源
-->
<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/ssmserverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<!--<mapper resource="mappers/UserMapper.xml"/>-->
<!--以包为单位引入映射文件
要求:
1、mapper接口所在的包要和映射文件所在的包一致
2、mapper接口要和映射文件的名字一致
-->
<package name="com.atguigu.mybatis.mapper"/>
</mappers>
4. 增删改查
增
<!--int insertUser();-->
<insert id="insertUser">
insert into t_user values(null,'admin','123456',23,'男')
</insert>
删
<!--int deleteUser();-->
<delete id="deleteUser">
delete from t_user where id = 7
</delete>
改
<!--int updateUser();-->
<update id="updateUser">
update t_user set username='ybc',password='123' where id = 6
</update>
查
<!--User getUserById();-->
<select id="getUserById" resultType="com.atguigu.mybatis.bean.User">
select * from t_user where id = 2
</select>
<!--List<User> getUserList();-->
<select id="getUserList" resultType="com.atguigu.mybatis.bean.User">
select * from t_user
</select>
- 查询的标签
select
必须设置属性resultType
或resultMap
,用于设置实体类和数据库表的映射关系 resultType
:自动映射,用于属性名和表中字段名一致的情况resultMap
:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况
5. 获取参数值的两种方式
$ 和 #
$
的本质就是字符串拼接
#
的本质就是占位符赋值$
使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号
#
使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号
1. 单个字面量类型的参数
-
若mapper接口中的方法参数为单个的字面量类型
-
此时可以使用
$
和#
以任意的名称获取参数的值,注意$
需要手动加单引号User getUserByUserName(String username);
<select id="getUserByUserName" resultType="user"> select * from t_user where username = '$username'; </select>
2. 多个字面量类型的参数
-
若mapper接口中的方法参数为多个
-
此时MyBatis会自动将这些参数放在一个map集合中,以**arg0,arg1…**为键,以参数为值;以param1,param2…为键,以参数为值
-
因此只需要通过
$
和#
访问map集合的键就可以获取相
对应的值,注意$
需要手动加单引号User getLogin(String username,String password);
<!--User getLogin(String username,String password);--> <select id="getLogin" resultType="User"> select * from t_user where username = #arg0 and password = #arg1; </select>
3. map集合类型的参数
-
若mapper接口中的方法需要的参数为多个时,此时可以手动创建map集合,将这些数据放在map中
-
只需要通过
$
和#
访问map集合的键就可以获取相对应的值,注意$
需要手动加单引号User checkLogin(Map map);
<select id="checkLogin" resultType="user"> select * from t_user where username = #username and password = #password; </select>
4. 实体类类型的参数
-
若mapper接口中的方法参数为实体类对象时
-
此时可以使用
$
和#
,通过访问实体类对象中的属性名获取属性值,注意$
需要手动加单引号int insertUser(User user);
<insert id="insertUser"> insert into t_user values(null,#username,#password,#age,#sex,#email); </insert>
5. 使用@Param标识参数
-
可以通过
@Param
注解标识mapper接口中的方法参数 -
此时,会将这些参数放在map集合中,以@Param注解的value属性值为键,以参数为值;以param1,param2…为键,以参数为值
-
只需要通过
$
和#
访问map集合的键就可以获取相对应的值,注意$
需要手动加单引号User checkLoginByParam(@Param("username") String username,@Param("password") String password);
<select id="checkLoginByParam" resultType="user"> select * from t_user where username = #username and password = #password; </select>
6. MyBatis的各种查询功能
1. 查询一个实体类对象
User getUserById(@Param("id") int id);
<select id="getUserById" resultType="User">
select * from t_user where id = #id
</select>
2. 查询一个list集合
List<User> getUserList();
<select id="getUserList" resultType="User">
select * from t_user
</select>
- 当查询的数据为多条时,不能使用实体类作为返回值,否则会抛出异常TooManyResultsException
- 但是若查询的数据只有一条,可以使用实体类或集合作为返回值
3. 查询单个数据
int getCount();
<select id="getCount" resultType="_integer">
select count(id) from t_user
</select>
4. 查询一条数据为map集合
Map<String, Object> getUserToMap(@Param("id") int id);
<!--结果: password=123456, sex=男 , id=1, age=23, username=admin-->
<select id="getUserToMap" resultType="map">
select * from t_user where id = #id
</select>
5. 查询多条数据为map集合
List<Map<String, Object>> getAllUserToMap();
<select id="getAllUserToMap" resultType="map">
select * from t_user
</select>
@MapKey("id")
Map<String, Object> getAllUserToMap();
@MapKey
设置map集合的键,值是每条数据所对应的 map集合
<!--
1=password=123456, sex=男, id=1, age=23, username=admin,
2=password=123456, sex=男, id=2, age=23, username=张三,
3=password=123456, sex=男, id=3, age=23, username=张三
-->
<select id="getAllUserToMap" resultType="map">
select * from t_user
</select>
7. 特殊SQL的执行
1. 模糊查询
List<User> testMohu(@Param("mohu") String mohu);
<select id="testMohu" resultType="User">
<!--select * from t_user where username like '%$mohu%'-->
<!--select * from t_user where username like concat('%',#mohu,'%')-->
select * from t_user where username like "%"#mohu"%"
</select>
2. 批量删除
int deleteMore(@Param("ids") String ids);
<delete id="deleteMore">
delete from t_user where id in ($ids)
</delete>
3. 动态设置表名
List<User> getAllUser(@Param("tableName") String tableName);
<select id="getAllUser" resultType="User">
select * from $tableName
</select>
4. 添加功能获取自增的主键
需求- 需求:在插入一条数据后需要获取该条记录的主键
- 方案
- 在一个单系统中常见的方法M是设置表中主键为自动递增,每次插入后,mybatis会将自动生成的主键赋值给指定的实体类字段
-
若数据库支持自动生成主键的字段(比如 MySQL和 SQL Server),则可以设置
useGeneratedKeys=”true”
,然后再把keyProperty
设置到目标属性上
(局限性很大、不利于项目后期扩展,实际开发中不推荐使用)int insertUser(User user);
<!--int insertUser(User user);--> <insert id="insertUser" useGeneratedKeys="true" keyProperty="id"> insert into t_user values( null, #username, #password, #age, #sex) </insert>
@Service public class UserService @Autowired private UserMapper userMapper; public int insertUser(User user) return userMapper.insertUser(user);
useGeneratedKeys设置为true后,mybatis会使用JDBC的getGeneratedkeys方法获取由数据库内部自动生成的主键,并将该值赋值给由keyProperty指定的字段;
-
对于不支持自增型主键的数据库(例如Oracle),则要先通过序列来模拟自增,每次插入数据前先从序列中拿到自增ID
(无论是单例项目还是分布式项目都适用)
-
- 在分布式系统中,则需要生成全局唯一主键ID
- 在一个单系统中常见的方法M是设置表中主键为自动递增,每次插入后,mybatis会将自动生成的主键赋值给指定的实体类字段
8. 自定义映射resultMap
1. resultMap处理字段和属性的映射关系
<!--resultMap:设置自定义映射
属性:
id:表示自定义映射的唯一标识
type:查询的数据要映射的实体类的类型
子标签:
id:设置主键的映射关系
result:设置普通字段的映射关系
association:设置多对一的映射关系
collection:设置一对多的映射关系
属性:
property:设置映射关系中实体类中的属性名
column:设置映射关系中表中的字段名
-->
<resultMap id="userMap" type="User">
<id property="id" column="id"></id>
<result property以上是关于MyBatis(详)的主要内容,如果未能解决你的问题,请参考以下文章