MyBatis
MyBatis 是一个开源、轻量级的数据持久化框架
学习文档:
https://www.cnblogs.com/hnkjdx-ssf/p/14942618.html
官方学习文档:https://github.com/xinyu-yudian/mybatis.git
原生mybatis核心配置文件
<?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="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments>
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册! //或在接口上添加@Mapper注解--> <mappers> <mapper resource="com/kuang/dao/userMapper.xml"/> </mappers> </configuration>
实体类设置别名
方式一:注解
<typeAliases> <typeAlias type="com.kuang.pojo.User" alias="User" /> </typeAliases>
方式二:指定一个包名,扫描实体类的包,它的默认别名就为这个类的类名,首字母小写
<typeAliases> <package name="com.kuang.pojo"/> </typeAliases>
@Alias("User") public class User {}
自动装配(spring)
<!--连接数据库--> <!--1.导入外部文件--> <context:property-placeholder location="mysql.properties"/> <!--2.配置数据源--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="url" value="${jdbc.url}"/> <property name="testWhileIdle" value="true"/> </bean> <!-- 配置SqlSessionFactory对象 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入数据库连接池 --> <property name="dataSource" ref="dataSource"/> <!-- 配置MyBaties全局配置文件:mybatis.xml --> <property name="configLocation" value="classpath:mybatis.xml"/> </bean> <!-- 配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 注入sqlSessionFactory --> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!-- mapper --> <property name="basePackage" value="com.xinyu.dao"/> </bean>
数据源
com.mchange.v2.c3p0.ComboPooledDataSource
org.apache.commons.dbcp2.BasicDataSource
<select>标签的属性
id:唯一指定标签的名字
resultType:查询结构返回的数据类型,自动进行封装操作
parameterType:给SQL语句传递参数的数据类型
resultMap:查询结果返回的数据类型,会根据映射文件中<resultMap>来完成数据封装
parameterMap:给SQL语句传递参数的数据类型,需要和<parameterMap.../>标签连用
模糊查询:https://blog.csdn.net/Adobe_java/article/details/118460709
mybatis工作流程:
-编写核心配置文件,环境信息,日志,缓存,Mapper等
-通过SqlSessionPactorBuild读取核心配置文件构建SqlSession
-通过SqlSessionOactor.getSession构建SqlSession
-使用SqlSession执行SQL语句
<Mapper>标签中加载XML文件几种方式
---URL
---CLASS
---RESOURCE
---PACKAGE
Mapper注意点:
接口和xml名字一样,路径一样(需到核心配置xml中配置<mappers>,因为maven工程约定:配置>编码)
接口的方法名和参数和返回值必须和xml保持一致
xml的命令空间必须全限定名
mybatis属性
resultMap:
resultMap 是一种“查询结果集---Bean对象”属性名称映射关系,
使用resultMap关系可将将查询结果集中的列一一映射到bean对象的各个属性
(两者属性名可以不同,配置好映射关系即可),适用与复杂一点的查询。
(1)适用于表的连接查询
(2)适用于表的一对多连接查询
(3)映射的查询结果集中的列标签可以根据需要灵活变化,
并且,在映射关系中,还可以通过typeHandler设置实现查询结果值的类型转换
resultType:
resultType 是一种“查询结果集---Bean对象”数据类型映射关系,使用resultType关系,即可使Bean对象接收查询结果集;
见名知意,该方法是通过查询结果集中每条记录(属性)的数据类型和Bean对象的数据类型作映射,
若两者都相同,则表示匹配成功,Bean可以接收到查询结果。
一般适用于pojo(简单对象)类型数据,简单的单表查询。
ParameterMap:
ParameterMap和resultMap类似,表示将查询结果集中列值的类型一一映射到java对象属性的类型上
parameterType
parameterType直接将查询结果列值类型自动对应到java对象属性类型上,不再配置映射关系一一对应
javaType:
javaType是用来指定pojo中对象属性的类型---(对象映射association用javaType)
ofType:
ofType指定的是映射到list集合属性中泛型的类型---(结果集collection用ofType)
mybatis常用sql语句
<?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指定对应的dao/mapper接口--> <mapper namespace="com.kuang.mapper.UserMapper"> <!--模糊查询--> <select id="seletc" parameterType="string" resultType="com.kuang.pojo.User"> select * from user where name like concat('%',#{name},'%'); </select> <!--根据id查询--> <select id="selectById" parameterType="int" resultType="com.kuang.pojo.User"> select * from user where id = #{id} </select> <!--新增--> <insert id="add" parameterType="com.kuang.pojo.User"> insert user(id,name,pwd) values (#{id},#{name},#{pwd}) </insert> <!--修改--> <update id="update" parameterType="com.kuang.pojo.User"> update user set name = #{name},pwd = #{pwd} where id = #{id} </update> <!--删除--> <delete id="delete" parameterType="int"> delete from user where id = #{id} </delete> </mapper>
配置 JAVA 对象属性与查询结果集中列名对应关系
resultMap 标签的使用
基本作用:
建立 SQL 查询结果字段与实体属性的映射关系信息
查询的结果集转换为 java 对象,方便进一步操作。
将结果集中的列与 java 对象中的属性对应起来并将值填充进去
!注意:与 java 对象对应的列不是数据库中表的列名,而是查询后结果集的列名
<resultMap id="BaseResultMap" type="com.online.charge.platform.student.model.Student"> <id property="id" column="id" /> <result column="NAME" property="name" /> <result column="HOBBY" property="hobby" /> <result column="MAJOR" property="major" /> <result column="BIRTHDAY" property="birthday" /> <result column="AGE" property="age" /> </resultMap> <!--查询时resultMap引用该resultMap --> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="Object"> select id,name,hobby,major,birthday,age from student where id=#{id} </select>
标签说明:
主标签:
id:该 resultMap 的标志
type:返回值的类名,此例中返回 Studnet 类
子标签:
id:用于设置主键字段与领域模型属性的映射关系,此处主键为 ID,对应 id。
result:用于设置普通字段与领域模型属性的映射关系
三. 动态 sql 拼接
if 标签
if 标签通常用于 WHERE 语句、UPDATE 语句、INSERT 语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。
<if test="name != null and name != ''"> and NAME = #{name} </if>
foreach 标签
foreach 标签主要用于构建 in 条件,可在 sql 中对集合进行迭代。也常用到批量删除、添加等操作中。
<!-- in查询所有,不分页 --> <select id="selectIn" resultMap="BaseResultMap"> select name,hobby from student where id in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
属性介绍:
collection:collection 属性的值有三个分别是 list、array、map 三种,分别对应的参数类型为:List、数组、map 集合。
item :表示在迭代过程中每一个元素的别名
index :表示在迭代过程中每次迭代到的位置(下标)
open :前缀
close :后缀
separator :分隔符,表示迭代时每个元素之间以什么分隔
choose 标签
有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis 提供了 choose 元素,按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when
的条件都不满则时,则执行 otherwise 中的 sql。类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。
if 是与(and)的关系,而 choose 是或(or)的关系。
<select id="getStudentListChoose" parameterType="Student" resultMap="BaseResultMap"> SELECT * from STUDENT WHERE 1=1 <where> <choose> <when test="Name!=null and student!='' "> AND name LIKE CONCAT(CONCAT('%', #{student}),'%') </when> <when test="hobby!= null and hobby!= '' "> AND hobby = #{hobby} </when> <otherwise> AND AGE = 15 </otherwise> </choose> </where> </select>
otherwise
sql片断(抽取出来的内容)
字符拼接
LIKE ‘%${name}%’ //#{}能够有效防止SQL注入,但是也有它的缺点,它会把传入的数据自动加上一个双引号 like concat('%','#{a}','%') liek "%"#{a}"%"
关联关系查询:
一对一:association -> javaType
一对多:conllection(集合) -> ofType
<?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="com.xinyu.mapper.fourTab.FourTabMapper"> <resultMap id="itemsMap" type="com.xinyu.entity.Items"> <id property="id" column="iid"/> <result property="name" column="name"/> <result property="price" column="price"/> <result property="detail" column="detail"/> <result property="pic" column="pic"/> <result property="createTime" column="createTime"/> </resultMap> <resultMap id="orderDetailMap" type="com.xinyu.entity.OrderDetail"> <id property="id" column="did"/> <result property="ordersId" column="orders_id"/> <result property="itemsId" column="items_id"/> <result property="itemsNum" column="items_num"/> <association property="items" resultMap="itemsMap"/> </resultMap> <resultMap id="ordersMap" type="com.xinyu.entity.Orders"> <id property="id" column="oid"/> <result property="userId" column="userId"/> <result property="number" column="number"/> <result property="createTime" column="createTime"/> <result property="note" column="note"/> <collection property="orderDetailList" resultMap="orderDetailMap"/> </resultMap> <resultMap id="userMap" type="com.xinyu.entity.User"> <id property="id" column="uid"/> <result property="username" column="username"/> <result property="birthday" column="birthday"/> <result property="sex" column="sex"/> <result property="address" column="address"/> <collection property="ordersList" resultMap="ordersMap"/> </resultMap> <select id="usersList" resultMap="userMap" parameterType="int"> SELECT u.id uid, u.username, u.birthday, u.sex, u.address, o.id oid, o.number, o.createtime, o.note, d.id id, d.items_num, i.id iid, i.`name`, i.price, i.detail, i.pic, i.createtime FROM `user` u LEFT JOIN orders o on o.user_id = u.id LEFT JOIN orderdetail d on d.orders_id = o.id LEFT JOIN items i on i.id=d.items_id WHERE u.id=#{uid} </select> </mapper>
储存缓存
一级缓存(默认) -- SqlSession级别
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
二级缓存 -- mapper级别
第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。
第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。
如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。
禁用二级缓存:userCache=false(<select>)
刷新二级缓存:flushCache=true -- select默认flushCache是false,insert、update、delete语句默认flushCache是true
开启二级缓存(mybatis核心控制文件):
<settings> <setting name="cacheEnabled" value="true"/> </settings>
<!--配置二级缓存--> <cache/>
a.junit
test.java.com.**.dao.UserdaoTest:
public class UserDaoTest { 1.查询全部: @Test public void test(){ //获取Sqlsession对象 SqlSession sqlSession= mybatisUtils.getSqlSession(); try{ //执行SQl UserDao userDao=sqlSession.getMapper(UserDao.class); List<User> userList=userDao.getUserList(); for(User user:userList){ System.out.println(user); } }catch (Exception e){ e.printStackTrace(); }finally { //关闭SqlSession sqlSession.close(); } } 2.id查询: @Test public void getUserById(){ SqlSession sqlSession= mybatisUtils.getSqlSession(); UserMapper mapper=sqlSession.getMapper(UserMapper.class); User user=mapper.getUserById(1); System.out.println(user); sqlSession.close(); } //模糊查询 @Test public void getUserById(){ SqlSession sqlSession= mybatisUtils.getSqlSession(); UserMapper mapper=sqlSession.getMapper(UserMapper.class); List<User> userList=mapper.getUserLike(value:"李"); for(User user:userList){ System.out.println(user); } sqlSession.close(); } //增删改需要提交事务 3.insert增加: @Test public void addUser(){ SqlSession sqlSession= mybatisUtils.getSqlSession(); UserMapper mapper=sqlSession.getMapper(UserMapper.class); if res=mapper.addUser(new User(id:4,name:"哈哈",pwd:"123333")); if(res>0){ System.out.println("插入成功!"); } //提交事务 sqlSession.commit(); sqlSession.close(); } Map运用: @Test public void addUser(){ SqlSession sqlSession= mybatisUtils.getSqlSession(); UserMapper mapper=sqlSession.getMapper(UserMapper.class); Map<string,object> map=new HashMap<String,Oobject> map.put("userid",5); map.put("password","222333"); mapper.addUser(map); sqlSession.close(); } 4.update修改: @Test public void updateUser(){ SqlSession sqlSession=MybatisUtils.getSqlSession(); userMapper mapper=sqlSession.getMapper(UserMapper.class); mapper.updateUser(new User(id:4,name:"呵呵",pwd:"123333")); if(res>0){ System.out.println("修改成功!"); } //提交事务 sqlSession.commit(); sqlSession.close(); } 5.delete删除: @Test public void deleteUser(){ SqlSession sqlSession=MybatisUtils.getSqlSession(); userMapper mapper=sqlSession.getMapper(UserMapper.class); mapper.deleteUser(id:4); } if(res>0){ System.out.println("删除成功!"); } //提交事务 sqlSession.commit(); sqlSession.close(); } }
注解开发
多参数 ——> arg0 , param1 ,
@Select("select * from user where id=#{id}") User getUserById(@Param("id") int id); @Insert("insert into user (id,name,pwd) values(#{id},#{name},#{password})") int addUser(User user); @Update("update user set name=#{name},pwd=#{password} where id=#{id}") int updateUser(User user); @Delete("delete from user where id = #{uid}") int deleteUser(@Param("uid") int id);
注解动态SQL
@SelectProvider:用于构建动态查询SQL。
@InsertProvider:用于构建动态新增SQL。
@UpdateProvider:用于构建动态更新SQL。
@DeleteProvider:用于构建动态删除SQL。
@UpdateProvider(type = BookProvider.class,method = "update") int update2(Book book);
class BookProvider{ public static String update(Book book){ return new SQL(){{ UPDATE("t_book"); if(book.getName()!=null){ SET("name=#{name}"); } if(book.getAuthor()!=null){ SET("author=#{author}"); } WHERE("id = #{id}"); } }.toString(); }
分页(PageHelper)
方式一:mybatis.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> <plugins> <!--分页插件--> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <property name="param1" value="value1"/> </plugin> </plugins> </configuration>
方式二:Spring 配置文件中配置拦截器插件
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注意其他配置 --> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <!--使用下面的方式配置参数,一行配置一个 --> <value> params=value1 </value> </property> </bean> </array> </property> </bean>
使用
start = (pageNow-1)*pageSize; PageHelper.offsetPage(start, pageSize); List<User> userList = userService.getUserList(user); PageInfo pageInfo = new PageInfo<>(userList); System.out.println(pageInfo); long total = pageInfo.getTotal(); long pageTotal = total%pageSize==0 ? total/pageSize : total/pageSize+1;