Mybatis知识汇总
Posted 爱分享的程序袁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis知识汇总相关的知识,希望对你有一定的参考价值。
什么是mybatis
mybatis是一个优秀的持久层框架,他对jdbc操作数据库的过程进行了封装,使开发者只用关注sql本身,不用去关注例如注册驱动,加载链接,得到statement,处理结果集等复杂的过程。
mybatis通过xml或者注解的方式,将要执行的各种sql语句配置起来,并通过Java对象和statement中的sql语句映射生成最终的sql语句,最后由mybatis框架执行sql语句,并将结果映射成Java对象返回。搭建一个mybatis
导入jar包,导入myBatis核心jar包和 数据库驱动jar包
在src下创建一个名为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>
<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/home_work"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
</configuration>
3.namespace属性<mapper namespace="dao.PhoneDao">
namespace 命名空间
多个mapper文件的namespace不能重复
命名:写的是 对应dao层接口的完全限定名(接口的包名+类名)
将一个mapper文件当成一个普通的java类
这里面的每一条sql语句 当成类中的方法
调用mapper中的某一条SQL的时候
namespace.SQL语句的id
4.id属性
是该SQL语句的唯一标识
在同一个mapper文件中 id不能重复
调用该SQL语句的时候 需要用到id
id可以想象成方法名字
一般跟接口中的方法名一致
resultType属性:
返回值类型 需要将查询出的数据 映射(转换)为哪一个实体类
无论是查询一条还是多条,写的都是实体类的完全限定名,不能写List<实体类>
java接口中 多条数据 还是用List<实体类>来接收
注意:
查询后的列名 要和 实体类中的属性名 对应上
对应不上的无法完成映射
新建了mapper文件后 需要到mybatis的配置文件中 进行配置,不然报错
<!-- 项目中的所有mapper文件都要到这进行配置,不然mybatis找不到
resource 写的是文件的路径 多个包之间用/分割-->
<mappers>
<mapper resource="dao/PhoneDao.xml"/>
</mappers>
5.SQL语句中的ParamterType属性
parameterType属性 ---- 参数类型
如果在执行增删改查的时候 需要传递参数 那么就需要些parameterType属性
与接口中参数类型保持一致
获取参数的方式:
1.#{参数名} -----》 推荐 如果只传递了一个int,string类型的参数
那么大括号中参数名 可以随意
2.${参数名}
#{}和${}的区别是什么?
答:${}是Properties文件中的变量占位符,它可以用于标签属性值和sql内部,属于静态
文本替换,比如${driver}会被静态替换为com.mysql.jdbc.Driver。#{}是sql的参数占位
符,Mybatis会将sql中的#{}替换为?号,在sql执行前会使用PreparedStatement的参数
设置方法,按序给sql的?号占位符设置参数值,比如ps.setInt(0, parameterValue),#
{item.name}的取值方式为使用反射从参数对象中获取item对象的name属性值,相当于
param.getItem().getName()。
注意:
如果传递的是一个实体类,那么大括号中写的是实体类中的属性名
如果获取的是实体类中的本身属性,那么大括号中直接写属性名字
如果获取的是级联属性,那么先获取级联的对象,在获取里面的属性
6.解决数据库中列名和实体类中的属性名不一致问题
1.在查询时将与属性名不一样的列名起 别名
2.在MyBatis配置文件中 配置启用驼峰映射方式
<settings>
<!-- 使用驼峰命名进行自动映射 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
使用驼峰方式映射 要求:
1.列名 多个单词之间用下划线连接 stu_name
2.实体类中 使用驼峰方式,将下划线去掉,第二个单词的首字符大写 如:stuName
7.实体类配置别名
在mybatis配置文件中,setting标签下写,位置不能换
<typeAliases>
<!--
package 为一个包下的所有类 配置别名
name属性 包的路径
在Mapper文件中只要用到了实体类,那么直接写类名即可
-->
<package name="model"/>
</typeAliases>
8.控制台打印sql语句的配置
9.面向接口编程的注意事项
1.Mapper文件的文件名字 和 接口的名字 对应,Mapper文件的namespace属性的值 要
和 接口的完全限定名一致
2.Mapper文件中的sql语句的id 要和 接口中的方法名字 一致
3.sql语句的返回值(resultType),要和接口中方法的返回值一致
4.接口中方法的参数 必须包含(但不限于) sql语句中 所需要的参(parameterType)
10.where标签和if标签
用法:
<select id="select" resultType="PhoneModel"
parameterType="PhoneModel">
select * from phone
<where>
<if test="phoneName != null and phoneName != ''">
and phone_name
like concat('%',#{phoneName},'%')
</if>
<if test="brandId != null">
and brand_id = #{brandId}
</if>
</where>
</select>
where标签作用:
where标签会自动生成一个where关键字
会自动去掉where条件后的第一个and关键字
每个条件都要加上and关键字
如果说一个where条件都没有,那么将不会生成where关键字
if标签作用:
与java中的if逻辑一致,没有else结构体
if标签可用在任意位置,不是只能用在where标签里面
test属性 写的是判断条件
如果要使用if标签对属性进行判断,那么要么传递
实体类,要么传递一个map集合
判断是获取的是 实体类中的属性名字,不需要#{}
多个判断条件之间用 and 单词来连接
注意:
如果使用if标签判断级联属性,那么首先要
判断该级联的对象是否非空,然后在判断级联对象
下的某些属性
11.set标签
<update id="update" parameterType="PhoneModel">
update phone
<set>
<if test="phoneName != null and phoneName != ''">
phone_name = #{phoneName},
</if>
<if test="phonePrice != null">
phone_price = #{phonePrice},
</if>
<if test="brandId != null">
brand_id = #{brandId},
</if>
</set>
where id = #{id}
</update>
作用:只能用于update操作
会生成一个set关键字
会将最后一个更新字段的逗号 去掉
更新每个字段后面都要加逗号
where关键字要写在set标签的外面
12.trim标签
prefix 前缀 是在trim标签之前拼接字符
prefixOverrides 去掉trim标签语句中第一个出现的关键字
suffix 后缀 是在trim标签之后拼接字符
suffixOverrides 去掉trim标签语句中最后一个出现的关键字
用法:
1.查询
<select id="selectTrim" parameterType="PhoneModel"
resultType="PhoneModel">
select * from phone
<trim prefix="where" prefixOverrides="and">
<if test="phoneName != null and phoneName != ''">
and phone_name
like concat('%',#{phoneName},'%')
</if>
<if test="brandId != null">
and brand_id = #{brandId}
</if>
</trim>
</select>
2.修改
<update id="updateTrim" parameterType="PhoneModel">
update phone
<trim prefix="set" suffixOverrides="," suffix="where">
<if test="phoneName != null and phoneName != ''">
phone_name = #{phoneName},
</if>
<if test="phonePrice != null">
phone_price = #{phonePrice},
</if>
</trim>
id = #{id}
</update>
3.新增
<insert id="insertTrim" parameterType="PhoneModel">
insert into phone
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="phoneName != null and phoneName != ''">
phone_name,
</if>
<if test="brandId != null">
brand_id,
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="phoneName != null and phoneName != ''">
#{phoneName},
</if>
<if test="brandId != null">
#{brandId},
</if>
</trim>
</insert>
13.choose标签
用法:
<select id="selectChoose" resultType="PhoneModel"
parameterType="PhoneModel">
select * from phone
<where>
<choose>
<when test="brandId != null">
and brand_id = #{brandId}
</when>
<when test="id != null">
and id = #{id}
</when>
<otherwise>
and 1=1
</otherwise>
</choose>
</where>
</select>
作用:跟java的if-else if-else逻辑是一样的
第一个when标签代表了if
其他的when标签代表了 else if
otherwise 代表了else
14.foreach标签
用法:
1.实现批量插入
<insert id="insertBatch" parameterType="list">
insert into phone
(phone_name,phone_price,brand_id)
values
<foreach collection="list" item="i" separator=",">
(#{i.phoneName},#{i.phonePrice},#{i.brandId})
</foreach>
</insert>
2.拼接or语句
<select id="selectPhoneName" resultType="PhoneModel"
parameterType="PhoneModel">
select * from phone
where phone_price > #{phonePrice}
<foreach collection="nameList"item="i" open=" and (" close=")" separator="or">
phone_name like concat("%",#{i},"%")
</foreach>
</select>
15.resultMap标签
用法:
<resultMap type="PhoneModel" id="phoneMap" autoMapping="true">
<id column="id" property="id"/>
<result column="phone_name" property="phoneName"/>
<result column="phone_price" property="phonePrice"/>
<result column="brand_id" property="brandId"/>
<association property="brandModel" javaType="BrandModel">
<id column="b_id" property="id"/>
<result column="brand_name" property="brandName"/>
</association>
</resultMap>
<select id="selectByMap" resultMap="phoneMap">
select
p.id,p.phone_name,p.phone_price,p.brand_id,
b.id b_id,b.brand_name
from phone p
left join brand b
on p.brand_id = b.id
</select>
注意:
1.只能用于查询
2.resultMap 和 resultType 二者只能出现一个
3.如果需要对结果集进行 一对一 或者 一对多的映射,
那么就要使用resultMap
作用:
1.解决列名与属性名不一致的问题
2.对结果进行一对一,一对多映射
用法:
select标签中resultMap属性写的是 一个resultMap标签的id
id属性 是resultMap标签的一个标识,不能重复
type属性 返回的类型,一般来讲,将主表对应的实体类当做返回类型
autoMapping属性:如果有一部分的查询出的列名和属性名 是一致的话
那么开启autoMapping将不需要为列名和属性名一致的
子标签:
1.id标签,用来映射主表的主键字段,只能出现一次
column 代表了列名,一定要根据查询后的列名来进行映射
property 代表了实体类中的属性名
javaType 代表了property所指定的属性在实体类中是什么类型
jdbcType 代表了column所指定的列在表中是什么类型
2.result标签 除主键以外字段 全部使用result标签进行映射
3.association标签 用于一对一映射
property 代表了实体类中的属性名字
javaType 代表了该属性是哪一个类型
16.嵌套查询
场景:查询所有手机并且 实体类中要 关联出 手机的品牌
<resultMap type="PhoneModel" id="queryMap">
<id column="id" property="id"/>
<!-- 其他字段使用驼峰自动映射 -->
<association property="brandModel" fetchType="lazy"
javaType="BrandModel" select="selectBrand" column="brand_id">
</association>
</resultMap>
<select id="selectPhone" resultMap="queryMap">
select * from phone
</select>
<!-- 一对一映射时自动被执行 -->
<select id="selectBrand" resultType="BrandModel" parameterType="int">
select * from brand where id = #{brandId}
</select>
用法:
select属性:在一对一映射的时候,自动调用 另外一条查询语句,将查询语句的返回
值,映射到 property所指定的属性上
column属性:指定的是查询后的一个列名可传递一个参数,也可传递多个 传递一个
直接写需要传递的列名即可传递多个参数:
{phoneName=phone_name,brandId=brand_id}
等号左面是 参数名,在第二条语句中获取的名字
等号右面是 需要传递的列名
fetchType属性:延迟加载 将fetchType指定为lazy则为延迟加载 只有嵌套查询的方
式 延迟加载才能生效
17.一对多关系查询
(只展示resultMap部分,select部分和上面一样)
<resultMap type="BrandModel" id="brandMap">
<id column="b_id" property="id"/>
<result column="brand_name" property="brandName"/>
<collection property="phoneList" autoMapping="true" ofType="PhoneModel">
<id column="id" property="id"/>
<!-- 其他属性交给驼峰进行自动映射 -->
</collection>
</resultMap>
collection标签作用:一对多的映射
property属性:list集合在实体类中的属性名
ofType属性:list集合中实体类的类型(尖括号中的类型)
18.嵌套的一对多查询
<!-- 嵌套的一对多映射 -->
<resultMap type="BrandModel" id="queryMap">
<id column="id" property="id"/>
<result column="brand_name" property="brandName"/>
<collection property="phoneList" ofType="PhoneModel"
select="selectPhoneByBrandId" column="id">
</collection>
</resultMap>
<select id="selectPhone" resultMap="queryMap">
select * from brand
</select>
<select id="selectPhoneByBrandId"
resultType="PhoneModel" parameterType="int">
select * from phone where brand_id = #{brandId}
</select>
19.Constructor标签
作用:实例化有带参的构造方法的对象
用法:
<resultMap type="BrandModel" id="conMap">
<constructor>
<idArg column="id" javaType="int"/>
<arg column="brand_name" javaType="string"/>
</constructor>
</resultMap>
注意:实体类中必须有带参数的构造
如果在<idArg>和<arg >标签中没有指定name属性,映射的顺序要和 有参构造中参
数顺序一致
以上是关于Mybatis知识汇总的主要内容,如果未能解决你的问题,请参考以下文章