mybatis复习-标签

关于sql操作

一 、定义SQL语句

select
属性介绍:
    id :唯一的标识符.
    parameterType:传给此语句的参数的全路径名或别名 例:com.test.poso.User或user
    resultType :语句返回值类型或别名。注意,如果是集合,那么这里填写的
是集合的泛型,而不是集合本身(resultType 与resultMap 不能并用)
<select id="userList" parameterType="user" resultType="User">
    select * from user where name =#{name}
</select>
insert
属性介绍:
    id :唯一的标识符
    parameterType:传给此语句的参数的全路径名或别名 例:com.test.poso.User
delete
例子:
<delete id="deleteUser" parameterType="int"> 
    delete from user 
    where id = #{id} 
</delete>
update
类似于insert

二、配置对象属性与查询结果集

resultMap
  • 建立SQL查询结果字段与实体属性的映射关系信息
  • 查询的结果集转换为java对象,方便进一步操作
  • 将结果集中的列与java对象中的属性对应起来并将值填充进去
  • 注意:与java对象对应的列不是数据库中表的列名,而是查询后结果集的列名
例:
<resultMap id="getStudentRM" type="EStudnet">
    <id property="id" column="ID"/>
    <result property="studentName" column="Name"/>
    <result property="studentAge" column="Age"/>
</resultMap>
<select id="getStudent" resultMap="getStudentRM">
    SELECT ID, Name, Age
    FROM TStudent
</select>

resultMap标签属性:
    id:该resultMap的标志
    type:返回值的类名,此例中返回EStudnet类
resultMap标签下的子标签:
    id:用于设置主键字段与领域模型属性的映射关系,此处主键为ID,对应id。
    result:用于设置普通字段与领域模型属性的映射关系
association】 一对一

在resultmap中使用,可以通过嵌套结果集(即在标签里再通过result标签来对应属性),也可以通过另一接口方法查询后获得结果集。

<!--自定义某个javaBean的封装规则
	type:自定义规则的Java类型
	id:唯—id方便引用
-->
<resultMap type="com.xiaoai.mybatis.bean.Employee" id="MyEmp">
    <!--指定主键列的封装规则
        id定义主键会底层有优化;column:指定哪一列
        property:指定对应的javaBean属性
    -->
	<id column="id" property="id" / >
    <!--定义普通列封装规则-->
	<result column="Last_name" property="lastName"/>
	<!--其他不指定的列会自动封装:我们只要写resultMap就把全部的映射规则都写上。-->
	<result column="email" property="emaiL"/>
	<result column="gender" property="gender"/>
</resultMap>

    
<!-- resultMap:自定义结果集映射规则; -->
<!-- public Employee getEmpById ( Integer id); -->
<select id="getEmpById" resultMap="MyEmp">
	select * from tbl_employee where id=#{id}
</select>

resultMap标签自定义结果集

<!--场景—·
	查询Employee的同时查询员工对应的部门门Employee===Department
	一个员工有与之对应的部门信息;
-->
<!-- 联合查询:级联属性封装结果集-->
<resultMap type="com.xiaoai.mybatis.bean.Employee" id="MyDifEmp">
    <id column="id" property="id"/>
    <result column="Last_name" property="LastName"/>
    <result column="gender" property="gender"/>
    
    <result column= "did" property="dept.ia"/>
    <result column="dept_name" property="dept.departmentName"/>
</resultMap>.

或者通过association标签对应
<resultMap type="com.xiaoai.mybatis.bean.Employee" id="MyDifEmp">
    <id column="id" property="id"/>
    <result column="Last_name" property="LastName"/>
    <result column="gender" property="gender"/>
    
    <!--association可以指定联合的javaBean对象property="dept":指定哪个属性是联合的对象
		javaType:指定这个属性对象的类型[不能省略]
	-->
    <association property="dept" javaType="com.xiaoai.mybatis.bear.Employee">
        <id column="did" property="id"/>
        <result column="dept_name" property="departmentName"/>
    </association>
</resultMap>

collection】 一对多/多对多

collection通过调用其他接口方法使用

相关属性
select表示调用另一个接口的查询方法
column将哪一列的值传递过去作为另一接口方法的参数 , 可以传递一个map类型的参数,例如:column=“key1=column1, key2=column2}”
property查询结果返回后封装到当前pojo哪一个属性。
fetchType设置延迟加载 =“lzay”
<resultMap type="com.xiaoai.mybatis.bean. Department" id="MyDeptStep">
    <id column="id" property="id" / >
    <id column="dept_name" property="departmentName" />
    <collection property="emps"
                select="com.xiaoai.mybatis.dao.EmployeeMapperPlus.getEmpsById" 
                column="id"> 
	</collection>
</resultMap>

<!-- public Department getDeptByIdstep(Integer id); -->
<select id="getDeptByIdStep" resultMap="MyDeptStep">
    select id,dept_name from tbl_dept where id=#{id}
</select>

如:查询歌单信息

  • user=创建者
    • 歌单对创建者==多对一
  • songList=歌单歌曲
    • 歌单对歌曲==一对多

需要注意属性:javaType和ofType
两者表示的不同:用ofType才能接收多个即接收列表

public class SongList implements Serializable {
    private Integer id;      // 主键
    private String title;    // 歌单标题
    private UserVo user;     // 用户
    private String pic;      // 歌单图片
    private String introduction;  // 简介
    private String style;         // 风格
    private List<Song> songList;  // 歌曲列表
	
	getXX和setxx省略......
}
<resultMap id="songDetailResultMap" type="com.ai.music.entity.SongList" >
        <id column="songlist_id" jdbcType="INTEGER" property="id"/>
        <result column="title" jdbcType="VARCHAR" property="title"/>
        <result column="pic" jdbcType="VARCHAR" property="pic"/>
        <result column="style" jdbcType="VARCHAR" property="style"/>
        <association property="user" javaType="com.ai.music.vo.UserVo">
            <id column="uid" jdbcType="INTEGER" property="id"/>
            <result column="username" jdbcType="VARCHAR" property="username"/>
            <result column="avator" jdbcType="VARCHAR" property="avator"/>
        </association>
        <collection property="songList" ofType="com.ai.music.entity.Song">
            <result column="name" property="name"/>
            <result column="album" property="album"/>
            <result column="type"  property="type"/>
            <result column="cover_pic"  property="coverPic"/>
            <result column="url"  property="url"/>
            <result column="lyric"  property="lyric"/>
            <result column="introduction"  property="introduction"/>
        </collection>
    </resultMap>
【discriminator】

鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为封装Employee:

例子:如果查出的是女生:就把部门信息查询出来,否则不查询;如果是男生,把last_name这一列的值赋值给email;
<resultMap type="com.xiaoai.mybatis.bean.Employee" id="MyEmpDis">
    <id column="id" property="id" />
    <result column="last_name " property= "LastName"/>
    <result column="email" property="email"/>
    <result column="gender" property="gender"/>
    
    <!--
		column:指定判定的列名
		javaType:列值对应的java类型
	-->
    <discriminator javaType="string" column="gender">
        
        <!--女生  参数:resultType=指定封装的结果类型﹔不能缺少。resultMap-->
        <case value="0" resultType= "com.xiaoai.mybatis.bean.Employee">
           <association property="dept" 
                        select="com.xiaoai.mybatis.dao.DepartmentMapper.getEmployeeById" 
                        column="d_id">
           </association>
        </case>
        
        <!--男生;如果是男生,把last_name这一列的值赋值给email; -->
        <case value="1" resultType="com.xiaoai.mybatis.bean.Employee">
             <id column="id" property="id"/>
             <result column="Last_name" property="LastName" />
             <result column= "last_name" property="emaiL" />
             <result column= "gender" property="gender" />
        </case>
    </discriminator>
</resultMap>

三、动态拼接SQL标签

【if】

通常用于WHERE语句中,通过判断参数值来决定是否使用某个查询条件,

也经常用于UPDATE语句中判断是否更新某一个字段,还可以在INSERT语句中用来判断是否插入某个字段的值

例:
<select id="getStudentListLikeName" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST       
    WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
</select> 

但是此时如果studentName是null或空字符串,此语句很可能报错或查询结果为空。

此时我们使用if动态sql语句先进行判断,如果值为null或等于空字符串,我们就不进行此条件的判断。

修改为:
<select id=" getStudentListLikeName " parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
    <if test="studentName!=null and studentName!='' ">     
        WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
    </if>     
</select>    
【foreach】

主要用于构建in条件,他可以在sql中对集合进行迭代。如下:

<delete id="deleteBatch"> 
    delete from user where id in
    <foreach collection="array" item="id" index="index" open="(" close=")" separator=",">
        #{id}
    </foreach>
</delete>
  
假如说参数为 int[] ids = {1,2,3,4,5}
那么打印之后的SQL如下:
  delete form user where id in (1,2,3,4,5)

foreach属性释义:

属性释义
collection属性值有三个:
>> list = List
>> array = 数组
>> map = map集合
>> 如果接口在传递参数时使用了@Param注解,则可以使用自己定义的名称
item表示在迭代过程中每一个元素的别名
index表示在迭代过程中每次迭代到的位置(下标)
open前缀
close后缀
separator分隔符,表示迭代时每个元素之间以什么分隔

foreach通常可以将之用到批量删除、添加等操作中。

【choose】

从多个选项中选择一个。

  • MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。

  • 当choose中所有when的条件都不满则时,则执行otherwise中的sql。

  • 类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。

  • if是与(and)的关系,而choose是或(or)的关系。

例:
<select id="getStudentListChooseEntity" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBLST      
    <where>     
        <choose>     
            <when test="studentName!=null and studentName!='' ">     
                    ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
            </when>     
            <when test="studentSex!= null and studentSex!= '' ">     
                    ST.STUDENT_SEX = #{studentSex}      
            </when>     
            <when test="studentBirthday!=null">     
                   ST.STUDENT_BIRTHDAY = #{studentBirthday}      
            </when>     
            <when test="classEntity!=null and classEntity.classID !=null and classEntity.classID!='' ">     
                   ST.CLASS_ID = #{classEntity.classID}      
            </when>     
            <otherwise>     
                   1=1 
            </otherwise>     
        </choose>     
    </where>     
</select>     

四、格式化输出

【where】
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
        WHERE 
        <if test="studentName!=null and studentName!='' ">     
            AND ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
        </if>     
        <if test="studentSex!= null and studentSex!= '' ">     
            AND ST.STUDENT_SEX = #{studentSex}      
        </if>     
</select>     

如果上面例子,参数studentName为null或’’,则或导致此sql组合成“WHERE AND”之类的关键字多余的错误SQL。这时我们可以使用where动态语句来解决。

  • 这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。

  • 此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

上面例子修改为:

<!-- 查询学生list,like姓名,=性别 -->     
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
    <where>     
        <if test="studentName!=null and studentName!='' ">     
            ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
        </if>     
        <if test="studentSex!= null and studentSex!= '' ">     
            AND ST.STUDENT_SEX = #{studentSex}      
        </if>     
    </where>     
</select>     
【set】
<!-- 更新学生信息 -->     
<update id="updateStudent" parameterType="StudentEntity">     
    UPDATE STUDENT_TBL      
       SET STUDENT_TBL.STUDENT_NAME = #{studentName},      
           STUDENT_TBL.STUDENT_SEX = #{studentSex},      
           STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},      
           STUDENT_TBL.CLASS_ID = #{classEntity.classID}      
     WHERE STUDENT_TBL.STUDENT_ID = #{studentID};      
</update>     

问题:当在update语句中使用if标签时,如果前面的if没有执行,则或导致逗号多余错误。

  • 使用set标签可以将动态的配置SET 关键字,和剔除追加到条件末尾的任何不相关的逗号。
  • 没有使用if标签时,如果有一个参数为null,都会导致错误,如下示例:

使用set+if标签修改后,如果某项为null则不进行更新,而是保持数据库原值。如下示例:

<!-- 更新学生信息 -->     
<update id="updateStudent" parameterType="StudentEntity">     
    UPDATE STUDENT_TBL      
    <set>     
        <if test="studentName!=null and studentName!='' ">     
            STUDENT_TBL.STUDENT_NAME = #{studentName},      
        </if>     
        <if test="studentSex!=null and studentSex!='' ">     
            STUDENT_TBL.STUDENT_SEX = #{studentSex},      
        </if>     
        <if test="studentBirthday!=null ">     
            STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},      
        </if>     
        <if test="classEntity!=null and classEntity.classID!=null and classEntity.classID!='' ">     
            STUDENT_TBL.CLASS_ID = #{classEntity.classID}      
        </if>     
    </set>     
    WHERE STUDENT_TBL.STUDENT_ID = #{studentID};      
</update>     
【trim】

trim(拼接字符串)是更灵活的去处多余关键字的标签,他可以实现where和set的效果。

trim标签相关属性说明
prefix=""前缀trim标签体中是整个字符串拼串后的结果。prefix给拼串后的整个字符串加一个前缀
prefixOverrides=""前缀覆盖去掉整个字符串前面多余的什么字符
suffix=""后缀suffix给拼串后的整个字符串加一个后辍
suffixOverrides=" "后缀覆盖去掉整个字符串后面多余的什么字符

where例子的等效trim语句:

<!-- 查询学生list,like姓名,=性别 -->     
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
    <trim prefix="WHERE" prefixOverrides="AND|OR">     
        <if test="studentName!=null and studentName!='' ">     
            ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
        </if>     
        <if test="studentSex!= null and studentSex!= '' ">     
            AND ST.STUDENT_SEX = #{studentSex}      
        </if>     
    </trim>     
</select>  

set例子的等效trim语句:

<!-- 更新学生信息 -->     
<update id="updateStudent" parameterType="StudentEntity">     
    UPDATE STUDENT_TBL      
    <trim prefix="SET" suffixOverrides=",">     
        <if test="studentName!=null and studentName!="">     
            STUDENT_TBL.STUDENT_NAME = #{studentName},
        </if>     
        <if test="studentSex!=null and studentSex!=" ">     
            STUDENT_TBL.STUDENT_SEX = #{studentSex}, 
        </if>     
        <if test="studentBirthday!=null ">     
            STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},      
        </if>     
        <if test="classEntity!=null and classEntity.classID!=null and classEntity.classID!='' ">     
            STUDENT_TBL.CLASS_ID = #{classEntity.classID}      
        </if>
    </trim>     
    WHERE STUDENT_TBL.STUDENT_ID = #{studentID};      
</update>     

五、配置关联关系

【association】

一对一
association通常用来映射一对一的关系,例如,有个类user,对应的实体类如下:(getter,setter方法省略)

private String id;//主键
private String userName;//用户姓名

有个类Article,对应的实体类如下:

private String id;//主键
private String articleTitle;//文章标题
private String articleContent;//文章内容

如果我想查询一个用户的时候,也查到他写的一篇文章,可以怎样写呢?在类user加入一个属性article

private String id;//主键
private String userName;//用户姓名
private Article article;//新增的文章属性

mapper.xml 在user类的mapper.xml这样配置

<resultMap id="userResultMap" type="test.mybatis.entity.User">
    <id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
    <result column="userName" property="userName" jdbcType="VARCHAR" javaType="java.lang.String"/>

    <-- 属性:
        property:查询结果返回后封装到当前pojo哪一个属性。
        select:表示调用另一个接口的查询方法 这里test.mybatis.dao.articleMapper为命名空间
        column:将那一列的值传递过去作为另一接口方法的参数 这里把user的id传过去
      -->
    <association property="article" 
                 column="id"
                 select="test.mybatis.dao.articleMapper.selectArticleByUserId"/>//test.mybatis.dao.articleMapper为命名空间
</resultMap>

article对应的xml这样写:

<resultMap id="articleResultMap" type="test.mybatis.entity.Article">
    <id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
    <result column="articleTitle" property="articleTitle" jdbcType="VARCHAR" javaType="java.lang.String"/>
    <result column="articleContent" property="articleContent" jdbcType="VARCHAR" javaType="java.lang.String"/>
</resultMap>

select语句...

注意:selectArticleByUserId方法对应在article对应的xml有这样的select语句

<select id="selectArticleByUserId" parameterType="java.lang.String" resultMap="ArticleResultMap">
    select * 
    from tb_article where userId=#{userId} 
</select>
【collection】

一对多
实体类增加对应属性

private String id;//主键
private String userName;//用户姓名
private List<Article> articleList;

userMapper.xml这样配置

<resultMap id="userResultMap" type="test.mybatis.entity.User">
    <id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
    <result column="userName" property="userName" jdbcType="VARCHAR" javaType="java.lang.String"/>
    //这里把user的id传过去
    <collection property="articleList" column="id" select="test.mybatis.dao.articleMapper.selectArticleListByUserId" />
</resultMap>
以下省略,类同,Mybatis会把结果封装成List类型。

如果我还想通过Article表另一张表,比如文章中有个fk_id,也可以像上面这样重复配置,把fk_id当做与另一张表关联的参数,那时就可以通过用户查到文章,查到文章关联的另一张表了。

六、标签

【bind】

可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值

属性:
name:相当于变量名
value:变量值,可以动态拼接,即可以写ognl表达式
使用时,直接使用变量即可,
<!-- 例:bind标签使用 -->
<select id="getEmpsTestInnerParameter" resultType="com.xiaoai.bean.Employee">
	<bind name="_lastName" value="'_'+lastName+'%'"/>  <!-- bind相当于定义变量名 -->
	<if test="_databaseId== 'mysqL'">
		select *from tbl_employee
        <if test="_parameter ! =null">
            where last_name like #{_lastName}  <!-- 这里的_lastName相当于引用变量名,即_lastName% -->
        </if>
	</if>
</select>

【sql】

定义sql,可静态可动态。更多用于写sql语句的一部分,就像写在配置文件中的sql常量

<!-- 抽取可重用的sgl片段。方便后面引用 -->
<sql id="insertcolumn ">
	<if test= "_databaserd=='oracle'">
		emp loyee_id , last_name , emai1
	</if>
	<if test="_databaseld=='mysqL' ">
		last_name , email,gender,d_idr
    </if>
</sql>

<!-- 通过include引用定义好的sql常量 -->
<insert id="addEmps">
	insert into tbl_employee(<include refid="insertcolumn"></include>)
	values
	<foreach collection="emps" item="emp" separator=",">
        (#{emp.lastName}, #{emp.email} ,#{emp.gender},#{emp.dept.id})
    </foreach>
</insert>
【include】

用于引用常量,也可以定义属性property,

sql标签内部就能使用自定义的属性,但取值的正确方式是${prop},不能使用#{prop}这种方式

<!-- 可以通过refid属性引入前面通过sql标签创建的slq常量-->
<include refid="insertColumn">
	<property name="testcoLomn" value="abc"/>
</include>

<!-- 
	include还可以自定义一些property,sql标签内部就能使用自定义的属性
	inciude-property:取值的正确方式${prop},
	#{prop}:不能使用这种方式-->
<sql id="insertCoLumn">
	<if test="_databaseId== 'oracle'">
		employee_id , last_name , email,${testColumn}
    </if>
			<!--取值通过#是取不到的-->
	<if test="_databaseld== 'mysql'"> <!-- 需用通过${testColumn}来获取-->
		last_name, email,gender,d_id
	</if>
</sql>

全局配置文件中的一些标签

configuration
	properties
	setting
	stypeAliases
	typeHandlers
	objectFactory
	plugins
	environments
		environment
			transactionManager
			dataSource
	databaseIdProvider
	mappers
【properties】标签

引入外部properties配置文件的内容;

属性:
resource:引入类路径下的资源
url:引入网络路径或者磁盘路径下的资源
【settings】标签

用于设置mybatis的运行时行为

例如:缓存、懒加载、驼峰命名策略等等等。

【typeAliases】标签

对javabean进行重命名,重命名后在接口对应配置文件.xml中返回类型填写时可以不用填写全限定类名,不过推荐填写全限定类名
注意:如果用package 进行重命名,若指定包下的子包包含和父包一样类名的类,会报错。

  • 对单个进行重命名
例如:
<typeAliases>
    <typeAlias alias="Author" type="domain.blog.Author" />
    <typeAlias alias="Blog" type="domain.blog.Blog" />
    <typeAlias alias="Comment" type="domain.blog.Comment"/>
    <typeAlias alias="Post" type="domain.blog.Post" />
    <typeAlias alias="Section" type="domain.blog.section"/>
    <typeAlias alias="Tag" type="domain.blog . Tag" />
</typeAliases>
  • 对多个进行重命名
    多个重命名就是指定包名,默认命名为类名小写
例如:
<typeAliases>
    <package name="domain.blog" />
</typeAliases>
  • 也可以在实体类上通过注解@alias实现类重命名
【databaseIdProvider】标签

mybatis根据不同的数据库厂商执行不同的执行sql

例如:
<databaseIdProvider type="DB_VENDOR">
    <! --为不同的数据库厂商起别名–->
    <property name="MysQL " value= "mysql" />
    <property name="Oracle" value="oracle" / >
</databaseIdProvider>

在slq标签里通过databaseId="databaseIdProvider标签下数据库取的名称"指定

例如:
<select id="getEmpById" resultType="com.xiaoai.empUser" databaseId="mysql">
    select *
    from tbl_employee 
    where id = #{id}
</select>
【mapper】标签

引入接口对应slq映射文件.xml

<configuration>
  <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
  <mappers>
      <mapper resource="com/xiaoai/dao/IUserDao.xml"/>
  </mappers>
</configuration>

属性:
resource引用类路径下的sql映射文件
url 引用网路路径或磁盘下的sql映射文件
class 引用(注册)接口全限定类名: 1-如果用注解,就是引入接口类。2-如果是映射文件,映射文件必须和接口同名,并且放在接口同一目录下;
【package】标签

注意:mappers下的package和重命名标签中的package区别:一个指定实体类包,一个指定dao包

<mappers>
    <!-- 用于指定Dao接口所在的包,当指定了之后就不需要再写mapper标签resource或者class属性了 -->
    <package name="com.xiaoai.dao"/>
</mappers>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值