mybatis的使用

回顾:

1. mybatis的介绍.
	mybatis的好处:
		是一个半自动化的ORM框架.
		动态sql.
		映射返回结果的一对多,多对一.
		性能优化,一级缓存,二级缓存,懒加载.
		简单易学,轻量级.
		
	mybatis和hibernate的区别: spring-data-jpa
	
2. mybatis的入门.
	1. 创建项目.	-> jar
	2. 导入依赖.	
		mybatis,mysql-connector-java,lombok,junit
	3. 准备数据库和实体类.	(dao层框架)
		... POJOs脚本文件-> 二阶段你没听课.
	4. 编写配置文件.
		mybatis-config.xml.
			1. 写xml文件的头.
			2. 导入mybatis的DTD约束.
			3. 跟标签. <configuration>
			4. 环境.	<environments default="mysql">
						<environment id="mysql">
							<transactionManager type="JDBC|MANAGED" />
							<dataSource type="POOLED|UNPOOLED|JNDI">
								<property name="driver" value=".." />
								<property name="url" value=".." />
								<property name="username" value=".." />
								<property name="password" value=".." />
							</dataSource>
						</environment>	
					 </environments>
			5. 引入映射文件. 	<mappers>
								<mapper resource="相对java|resources的路径" />
							</mappers>
							
		
		映射文件.xml
			1. 写xml文件的头.
			2. 导入mybatis的DTD约束.
			3. 跟标签. <mapper namespace="映射文件的唯一标识">
			4. 编写CRUD.
				<select id="sql的唯一标识" resultType="返回结果">
					sql语句.
				</select>
	5. 测试.
		1. InputSteam is = Resources.getResourcesAsStream("resource");
		2. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
		3. SqlSession sqlSession = factory.openSession();
		4. sqlSession.selectOne(映射文件唯一标识.SQL语句唯一标识);
			Too Many Results Exception
			
			
3. 日志框架的选择.
    日志框架的要求:
        1. 将日志输出到当前系统的本地文件中.
        2. 区别输出日志信息类别.
        3. 定制输出的格式.
        4. 通过外部的配置文件随意的修改日志的信息.
        5. 一日一日志.
        6. 优异的性能.
    挑选日志框架:
        日志的门面								日志的实现
        commons-logging							JUL
        SLF4J									log4j
        jboss-logging							log4j2
                                                logback
    导入SLF4J和logback的依赖.
        ...
    赋值logback.xml的日志配置文件.
        ...
    编写日志信息.
        @Slf4j
        log.error|info|debug
	
4. 基于Mapper接口实现mybatis.
	1. 接口名和映射文件名保持一致.
	2. 映射文件的namespace属性写接口的全路径.
	3. 接口的抽象方法要和映射的sql/标签一一对应.	
	4. 放在同一目录下.(不是硬性要求)
	
5. 核心配置文件的详解.
	1. properties
		引入外部的properties文件,内部通过${key}
	2. settings.
		配置mybatis运行时的环境 -> 驼峰映射....
	3. typeAliases
		别名.
	4. plugins.
		.. 分页助手.
	5. environments
		环境.
	6. mappers
		<mappers>
			<mapper resource|url|class="" />
			扫描映射文件
			<package name="包名" />
		</mappers>
	
6. 核心API详解.
	SqlSessionFactoryBuilder
	SqlSessionFactory
	SqlSession
	Executor

一. mybatis的CRUD.

1. select.

1. 根据年龄做等值判断.
	select * from user where age = #{age}
	select * from user where age = ${value}
	
	-> parameterType映射抽象方法的参数类型.
	-> #{} 和 ${}的区别.  (面试题)
		1. 当传入一个参数时, #{随便写},${value}(3.5.2以下的版本必须写value)
		2. #{}可以防止sql注入,  ${}sql的字符串拼接.
2. 根据名称做模糊查询.
	select * from user where name like  "%"#{name}"%"
    select * from user where name like concat('%',#{name},'%')
	
	-> 因为#{}防止sql注入,会将传入的值用单引号包起来,导致直接拼接%会失效.
		"%"#{值}"%"
		concat('%',#{值},'%')
3. 根据名称做模糊查询并且根据年龄做等值判断.
	List<User> findByNameLikeAndAge(String name,Integer age);
	由于传入了多个且类型不一致的参数,导致parameterType无法声明.
	三种解决方案:
		1. 采用注解传参.
    List<User> findByNameLikeAndAge(@Param("name") String name,@Param("a") Integer age);
    
    <select id="findByNameLikeAndAge" resultType="User" >
        select * from user where name like "%"#{name}"%" and age = #{a}
    </select>
    
		2. 采用POJO类传参.
	List<User> findByNameLikeAndAgeForUser(User user);

    <select id="findByNameLikeAndAgeForUser" resultType="User" parameterType="User">
        select * from user where name like "%"#{name}"%" and age = #{age}
    </select>
        
		3. 采用Map传参.
    根据名称做模糊查询并且根据年龄做等值判断同时做分页.    
    // 根据名称做模糊查询和用户年龄查询分页.
    List<User> findByNameLikeAndAgeLimitForMap(Map<String,Object> map);
	
    <select id="findByNameLikeAndAgeLimitForMap" resultType="User" >
        select * from user where name like "%"#{user.name}"%" and age = #{user.age} limit #{offset},#{size}
    </select>

2. insert

添加一条用户信息.
抽象方法:	Integer save(User user);
映射文件:	<insert id="save" parameterType="User">
			insert into user (name,age,hobby) values (#{name},#{age},#{hobby})
			
如果主键是自增,获得自增后的主键值.
	方式1:
		<insert useGeneratedKeys="true" keyProperty="oid(Object id)" >
		
	方式2
    	<selectKey keyProperty="oid" resultType="Integer">
    		select LAST_INSERT_ID()
    	</selectKey>
在添加之后,通过传入的user对象,接收自增后的id.
	

3. update&delete

update:
抽象方法:	Integer updateById(User user);
映射文件:	<update id="updateById" parameterType="User">
				update user set name = #{name},.... where id = #{id}
		   </update>
		   
delete:
抽象发放:	Integer deleteById(@Param("id") Integer id);
映射文件:   <delete id="deleteById" >
				delete from user where id = #{id}
		   </delete>

二. ResultMap的使用.

当实体类的属性名和关系表的字段名无法自动映射时,采用resultMap手动映射.

<select resultMap="唯一标识">

<resultMap id="唯一标识" type="抽象方法的返回值类型." >
	<id property="属性名" column="字段名" />
    <result property="属性名" column="字段名" />
</resultMap>    
    
mybatis默认开启了自动映射,resultMap只编写无法自动映射的属性和字段即可.
    (当返回值类型设计到了一对多/多对一映射时,默认映射级别PARTIAL无法自动映射)

三. 一对多和多对一.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y5Ao0MUH-1573006317909)(img/1569487180009.png)]

1. 多对一.

R:
	关系表维护关系靠的是外键
O:
	一的一方的类对象.
M:
	ResultMap -> 映射sql语句的返回结果.
<resultMap id="shoeAndBrandResultMap" type="Shoe">
    <!--映射oid和普通字段-->
    <id property="id" column="id" />
    <result property="title" column="title" />
    <result property="size" column="size" />
    <result property="color" column="color" />
    <result property="price" column="price" />
    <result property="stock" column="stock" />
    <!--维护多对一的关系-->
    <association property="brand" javaType="Brand" columnPrefix="b_" >
        <!--映射oid和普通字段-->
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="description" column="description" />
        <result property="created" column="created" />
    </association>
</resultMap>


<!--    // 根据id查询鞋子和其品牌信息.-->
<!--    Shoe findShoeAndBrandById(@Param("id") Integer id);-->
<select id="findShoeAndBrandById" resultMap="shoeAndBrandResultMap" >
    select
        s.*,
        b.id as b_id,
        b.name as b_name,
        b.description as b_description,
        b.created as b_created
    from
        shoe s ,
        brand b
    where
        s.brand_id = b.id
        and s.id = #{id}
</select>

2. 一对多.

R:
	......
O:
	// 维护 一 对 多 的关系
	private Set<Shoe> shoeSet;
M:
<!--    封装一对多关系的resultMap-->
<resultMap id="brandAndShoesResultMap" type="Brand">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <result property="description" column="description" />
    <result property="created" column="created" />
    <!--        维护一对多关系-->
    <collection property="shoeSet" ofType="Shoe" columnPrefix="s_">
        <id property="id" column="id" />
        <result property="title" column="title" />
        <result property="size" column="size" />
        <result property="color" column="color" />
        <result property="price" column="price" />
        <result property="stock" column="stock" />
        <result property="state" column="state" />
    </collection>
</resultMap>

<!--    // 根据id查询品牌和其对应的全部鞋子.-->
<!--    Brand findBrandAndShoesById(@Param("id") Integer id);-->
<select id="findBrandAndShoesById" resultMap="brandAndShoesResultMap">
    select
    b.*,
    s.id s_id,
    s.title s_title,
    s.size s_size,
    s.color s_color,
    s.price s_price,
    s.stock s_stock,
    s.state s_state
    from
    brand b inner join shoe s on b.id = s.brand_id
    where
    b.id = #{id}
</select>

四. 动态sql.

1. if + where

当条件很多,并且可有可无,之前需要手动封装很多个sql,才能完成指定业务.
if -> 可以通过
	<if test="条件判断"></if> 
	如果条件判断返回true -> 添加if标签体内的查询条件.
	如果条件判断返回false -> 忽略if标签体内的查询条件.
where -> 将全部查询条件包裹在<where>标签体内.
	1. <where>标签体内有查询条件,添加where关键字,
	   <where>标签体内没有查询条件,不添加where关键字.
    2. <where>会去除前缀多余的一个and|or   

例子:
<select id="findByCondition" resultType="Shoe" parameterType="Shoe">
    select
    *
    from
    shoe
    <where>
        <if test="title != null and title != ''">
            title like "%"#{title}"%"
        </if>

        <if test="size != null and size != ''">
            and size = #{size}
        </if>

        <if test="color != null and color != ''">
            and color = #{color}
        </if>

        <if test="price != null">
            and price = #{price}
        </if>

        <if test="stock != null and stock >= 0">
            and stock = #{stock}
        </if>

        <if test="state != null and state != ''">
            and state = #{state}
        </if>
    </where>
</select>           

2. if + set

当修改的字段变化时,可以使用if+set解决问题.
if(同上)
set
	1. 当set标签体内有内容时,添加set关键字.
	   当set标签体内没有内容时,不添加set关键字.
	2. 去除修改内容中后缀多余的一个.
<update id="updateById" parameterType="Shoe" >
    update
        shoe
    <set>
        id = #{id},
        <if test="title != null and title != ''">
            title = #{title},
        </if>

        <if test="size != null and size != ''">
            size = #{size},
        </if>

        <if test="color != null and color != ''">
            color = #{color},
        </if>

        <if test="price != null">
            price = #{price},
        </if>

        <if test="stock != null and stock >= 0">
            stock = #{stock},
        </if>

        <if test="state != null and state != ''">
            state = #{state}
        </if>
    </set>
    where
        id = #{id}
</update>

3. if + trim

trim可以代替set或where.
自定义指定代替什么关键字,自定义去除多余的什么前缀和什么后缀.
trim的4个属性.
	prefix		->		指定前缀
	prefixOverrides		-> 		去除多余的前缀.
	
	suffix		->		指定后缀
	suffixOverrides		->		去除多余的后缀.

4. foreach.

循环遍历.
	select * from table where id in (?,?,?,?)

<foreach 
	collection="array|list|map-key" 
	open="开始" separator="间隔" close="结束" 
	item="遍历的值的别名">
	#{别名}
</foreach>	


	select * from table where id in (?,?,?,?)
    <select id="findByIdListIn" resultType="shoe">
        select * from shoe where id in
        <foreach collection="array|list|map-key" open="(" separator="," close=")" item="id">
            #{id}
        </foreach>
    </select>

批量添加.
	insert into table (name,age) values (?,?),(?,?),(?,?).....

	batchSave(Shoe[] shoeArray);
    batchSave(List<Shoe> shoeList);
    batchSave(Map<String,Object(传入set集合)> map);
        
    insert into table (name,age) values
    <foreach collection="array" separator="," item="shoe">
        (#{shoe.name},#{shoe.age})
    </foreach>    

5. choose + when + otherwise

switch + case + default.
当需要涉及到多个查询条件使用其中一个时,多选一的情况,又动态sql没有提供elseif的功能,为了避免多次判断,采用
choose + when + otherwise的方式.
<select id="findByState" resultType="Shoe">
    select * from shoe where
    <choose>
        <when test="flag == 0">state = 'UP'</when>
        <otherwise>state = 'DOWN'</otherwise>
    </choose>
</select>

五. mybatis的性能优化.

me},#{shoe.age})


### 5. choose + when + otherwise

```xml
switch + case + default.
当需要涉及到多个查询条件使用其中一个时,多选一的情况,又动态sql没有提供elseif的功能,为了避免多次判断,采用
choose + when + otherwise的方式.
<select id="findByState" resultType="Shoe">
    select * from shoe where
    <choose>
        <when test="flag == 0">state = 'UP'</when>
        <otherwise>state = 'DOWN'</otherwise>
    </choose>
</select>

五. mybatis的性能优化.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值