mybatis

1.基本概念

持久层:封装访问数据库的细节,为业务逻辑层提供面向对象的API。
完善的持久层应具备以下3个特点:
1. 代码的可重用性高,能够完成所有的数据库访问操作。
2. 可以支持多种数据库平台。
3. 具有相对独立性,当持久层的实现发生变化时,不会影响上层的实现。
 
MyBatis:本是apache的一个开源项目iBatis,后改名为MyBatis。MyBatis是一种”半自动化”的ORM框架。
 
下载地址:http://mvnrepository.com/artifact/org.mybatis/mybatis

中文帮助文档:http://www.mybatis.org/mybatis-3/zh/index.html

+杂+
三个jar包
junit-4.8.2.jar
mybatis-3.4.4.jar
ojdbc6.jar

<!-- #{}  (Map)%${value}% 只能是value或者key,大小写不能变-->
  <select id="queryLike" resultType="com.pojo.Shop">
    <!--select * from shop where shopName like #{aaa}-->
      select * from shop where shopname like '%${value}%'  
  </select>  
  
   <!-- 如果入参是复杂对象,如实体、Map对象时,#(写对应的实体当中的属性名或key) -->
  <!--jdbcType=VARCHAR 类型要大写。java中的String类型,sql中的varchar类型,这样做这个类型就可以为空了  -->
  <insert id="addShop">
    insert into shop values(#{shopId},#{shopName},#{shopAddress,jdbcType=VARCHAR},#{contact})
  </insert> 

 <!--  <update id="updateShop">
    update shop set  shopid=#{aaa},shopname=#{aaa},shopaddress=#{aaa},contact=#{aaa} 
  </update> -->
  <!-- shopname=#{shopName} {}中的属性要跟shop对象里面的统一,大小写不能变 -->

<select id="queryBy" resultType="com.pojo.Shop">
      select * from shop where 1=1
      <!-- _parameter:表示接口方法中的参数 即value或者key  这种模式是3个并列查询,条件都必须满足才行-->
      <!-- 去掉 <if test="_parameter !=null and  _parameter=''">
           则可以随便写几个,写几个就满足几个的条件-->
      <if test="_parameter !=null and  _parameter=''">
             <!-- 可以就写shopName属性 -->
             <if test="shopName !=null and shopName != '' ">
              and shopname like '%${shopName}%'
             </if> 
             <if test="shopAddress !=null and shopAddress != '' ">
              and shopaddress like '%${shopAddress}%'
             </if> 
             <if test="contact !=null and contact != '' ">
              and contact like '%${contact}%'
             </if> 
      </if>     
  </select> 

2.MyBatis配置文件+Sql映射文件

MyBatis配置文件,如mybatis-config.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="驱动路径"/>
<property name="url" value="连接地址"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
其中可在<configuration>标签上添加如下常用配置:

<settings>
<!-- 控制台显示sql语句(开发使用) -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

<typeAliases>
<!-- 设置类型别名 区分大小写 -->
<typeAlias type="domain.blog.Blog" alias="Blog"/>
<!-- 定义指定包下的所有类型别名(同类名),该方式的别名不区分大小写(推荐) -->
<package name="domain.blog"/>
</typeAliases>
 
<mappers>标签的4种配置方式:
<mappers>
<!-- 使用相对类路径 -->
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
<!-- 使用url完整路径 -->
<mapper url="file:///org/mybatis/example/BlogMapper.xml"/>
<!-- 使用映射器接口类 -->
<mapper class="org.mybatis.example.BlogMapper"/>
<!-- 注册指定包中的所有映射器接口(推荐) -->
<package name="org.mybatis.example"/>
</mappers>

Sql映射文件,如BlogMapper.xml:
<?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">
<select id="selectBlog" resultType="Blog">
select * from Blog where id=#{id}
</select>
</mapper>

3.从XML中构建SqlSessionFactory

从XML中构建SqlSessionFactory:
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
 
SqlSessionFactoryBuilder:
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。因此SqlSessionFactoryBuilder实例的最佳作用域是方法作用域(也就是局部方法变量)。
 
SqlSessionFactory:
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。使用SqlSessionFactory的最佳实践是在应用运行期间不要重复创建多次,因此SqlSessionFactory的最佳作用域是应用作用域(即单例模式或者静态单例模式)。
 
SqlSession:
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。绝对不能将SqlSession实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将SqlSession实例的引用放在任何类型的管理作用域中,比如Servlet架构中的HttpSession。如果你现在正在使用一种Web框架,要考虑SqlSession放在一个和HTTP请求对象相似的作用域中。换句话说,每次收到HTTP请求,就打开一个SqlSession,返回一个响应,就关闭它。这个关闭操作是很重要的,你应该把这个关闭操作放到finally块中以确保每次都能执行关闭。
如:SqlSession session = sqlSessionFactory.openSession();

4.映射器实例(Mapper Instances)+标签详解

1.映射器实例(Mapper Instances):
映射器是创建用来绑定映射语句的接口。映射器接口的实例是从SqlSession中获得的。因此从技术层面讲,映射器实例的最大作用域是和SqlSession相同的,因为它们都是从 SqlSession 里被请求的。尽管如此,映射器实例的最佳作用域是方法作用域。
如:BlogMapper mapper = session.getMapper(BlogMapper.class);

Sql映射文件标签详解:
cache:指定命名空间的缓存配置。
cache-ref:引用其他命名空间的缓存配置。
resultMap:指定如何从数据库结果集中封装具体数据(用于复杂查询)。
sql:指定可重用的语句块。
insert:映射插入语句。
update:映射更新语句。
delete:映射删除语句。
select:映射查询语句。

2.标签详解:
<mapper namespace="com.dao.ShopMapper">
namespace:命名空间的唯一标识符,一般为接口的完全限定名(包名.接口名)。
 
<select id="queryAll" resultType="com.pojo.Shop">
select * from shop
</select>
id:在命名空间中唯一的标识符,用于查找具体的SQL命令,一般为DAO中的方法名。
resultType:指定返回类型(类的完全限定名或别名),返回类型应能映射到数据库结果集中的单条数据,不能与resultMap同时使用。
_____________________
<select id="queryLike" parameterType="string" resultType="com.pojo.Shop">
<!--
select * from shop where shopname like #{sn}
-->
select * from shop where shopname like '%${value}%'
</select>
parameterType:指定输入参数类型(类的完全限定名或别名),可省略该配置,因为MyBatis框架可以自动解析出传入参数的具体类型。
#{}:表示占位符,会被解析成jdbc中的?号。若输入参数类型为对象则为属性,map则为key,简单类型则可自定义。
${}:拼接符,若输入参数类型为对象则为属性,map则为key,简单类型则必须为value。
_____________________
<insert id="add" parameterType="com.pojo.Shop">
insert into shop values(SEQ_SHOP_SHOPID.nextval,#{shopName},#{shopAddress},#{contact})
</insert>
parameterType:这里的输入参数为对象类型,所以#{}中为该对象的属性名。

5.映射器实践规则

映射器最佳实践规则:
1. 将DAO类定义成DAO接口。
如:public class ShopMapper->public interface ShopMapper
2. 将SQL映射文件名与DAO接口名一致。
如:ShopMapper.xml和public interface ShopMapper
3. 将SQL映射文件与DAO接口保存在同一包(目录)下。
如:ShopMapper.xml和public interface ShopMapper均在com.dao包下
4. 设置SQL映射文件mapper标签的namespace属性值为DAO接口的完全限定名。
如:<mapper namespace="com.dao.ShopMapper">
5. 设置SQL映射文件中相应操作的id属性值与DAO接口中的方法名一致。
如:<select id="queryAll" resultType="shop">和List<Shop> queryAll()
6. 设置SQL映射文件中的返回类型与DAO接口中对应方法的返回类型一致。
如:<select id="queryAll" resultType="shop">和List<Shop> queryAll()
7. 通过SqlSession对象的getMapper方法获取对应的映射器实例。
如:ShopMapper mapper = session.getMapper(ShopMapper.class)
8. 通过映射器实例调用DAO接口中对应的方法。
如:mapper.queryAll()

6.动态sql(if)

如:输入参数为简单类型String
<select id="queryIfByBase" resultType="shop">
select * from shop where 1=1
<!-- 如果输入参数不为null并且不为空就追加条件 -->
<if test="_parameter != null and _parameter != ''">
and shopname like '%${value}%'
</if>
</select>
_parameter:内置属性,表示接口中方法的参数。
 
___________________
如:输入参数为对象类型com.pojo.Shop
<select id="queryIfByReference" resultType="shop">
select * from shop where 1=1
<if test="_parameter != null">
<if test="shopName != null and shopName != ''">
and shopname like '%${shopName}%'
</if>
<if test="shopAddress != null and shopAddress != ''">
and shopaddress like '%${shopAddress}%'
</if>
</if>
</select>
shopName和shopAddress:表示对象Shop中的属性名。

7.动态sql(choose,when,otherwise)

动态choose,when,otherwise:类似于switch语法,匹配某个条件即停止向后判断,都不满足则执行otherwise条件。

<select id="queryChooseWhenOtherwise" resultType="shop">
select * from shop where 1=1
<choose>
<when test="shopName != null and shopName != ''">
and shopname like '%${shopName}%'
</when>
<when test="shopAddress != null and shopAddress != ''">
and shopaddress like '%${shopAddress}%'
</when>

<otherwise>
and contact like '%139%'
</otherwise>
</choose>
</select>

8.动态sql(where)

动态where:动态拼接and或or关键字。
<select id="queryWhere" resultType="shop">
select * from shop
<where>
 <if test="_parameter != null">
<if test="shopName != null and shopName != ''">
and shopname like '%${shopName}%'
</if>
<if test="shopAddress != null and shopAddress != ''">
and shopaddress like '%${shopAddress}%'
</if>
 </if>
</where>
</select>

9.动态sql(set)

动态set:动态拼接逗号(,)。
<update id="updateSet">
update shop
<set>
<if test="_parameter.shopName != null and _parameter.shopName != ''">
shopname=#{_parameter.shopName},
</if>

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

<if test="contact != null and contact != ''">
contact=#{contact},
</if>
</set>
where shopid=#{shopId}
</update>

10.动态sql(foreach)

动态foreach:主要用于构建in条件,它可以在SQL语句中进行迭代一个集合。
属性详解:
collection:若接口中方法的参数类型是List则为list,数组为array,Map为键,实体为属性。
item:当前迭代的元素。
index:当前迭代的次数。
open:开始字符串。
close:结束字符串。
separator:分隔符。
 
迭代List:
<select id="queryForeachByList" resultType="shop">
select * from shop where shopid in
<foreach collection="list" item="sid" open="(" separator="," close=")">
#{sid}
</foreach>
</select>
 
迭代数组:
<select id="queryForeachByArray" resultType="shop">
select * from shop where shopid in
<foreach collection="array" item="sid" open="(" separator="," close=")">
#{sid}
</foreach>
</select>
 
迭代Map:
<select id="queryForeachByMap" resultType="shop">
select * from shop where shopid in
<foreach collection="shopIds" item="sid" open="(" separator="," close=")">
#{sid}
</foreach>
</select>

11.重用语句块(include)

sql:指定可重用的语句块。
<!-- 指定可重用的语句块 -->
<sql id="commSql">
<if test="_parameter != null">
<if test="shopName != null and shopName != ''">
and shopname like '%${shopName}%'
</if>
<if test="shopAddress != null and shopAddress != ''">
and shopaddress like '%${shopAddress}%'
</if>
</if>
</sql>
 
<select id="queryIfByReference" resultType="shop">
select * from shop where 1=1
<!-- 引用语句块 -->
<include refid="commSql"/>
</select>
 
<select id="queryWhere" resultType="shop">
select * from shop
<where>
<!-- 引用语句块 -->
<include refid="commSql"/>
</where>
</select>

12.调用存储过程

调用存储过程:
过程定义:
create or replace procedure proc_shop
(p_shopId shop.shopid%type,p_shopName out shop.shopname%type)
as
begin
select shopname into p_shopName from shop where shopid=p_shopId;
end;
 
SQL映射:
<select id="callProc" statementType="CALLABLE">
call proc_shop(#{shopId},#{shopName,mode=OUT,jdbcType=VARCHAR})
</select>
 
DAO接口:void callProc(Map<String, String> map);

13.resultMap(一对一和多对一)

一、resultMap:指定如何从数据库结果集中封装具体数据(用于复杂查询)。

二、one-to-one(一对一)和many-to-one(多对一) 关联主表查询:在子表对应的实体中定义主表对应的实体的属性。
<!—
many-to-one(多对一)映射:
id:唯一的标识符(自定义)。
type:指定返回类型(类的完全限定名或别名)。
-->
<resultMap id="many2oneResultMap" type="product">
<!--
id标签:用于映射主键字段。
property:实体的属性名。
column:查询的字段名(列名)。
将column指定的值映射为property指定的值。
-->
<id property="productId" column="productid"/>
<!-- result标签:用于映射普通字段 -->
<result property="title" column="title"/>
_______________
<!--
association标签:用于关联主表(即one-to-one和many-to-one)。
javaType:property属性值对应的具体类型(类的完全限定名或别名)。
-->
<association property="shop" javaType="shop">
<result property="shopName" column="shopname"/>
<result property="shopAddress" column="shopaddress"/>
</association>
</resultMap>
_______________
<select id="many2one" resultMap="many2oneResultMap">
select productid,title,shopname,shopaddress
from product p inner join shop s on p.shopid=s.shopid order by productid
</select>

14.resultMap(一对多和多对多)

三、one-to-many(一对多)和many-to-many(多对多) 关联子表查询:在主表对应的实体中定义子表对应的实体的集合属性。

<!-- one-to-many(一对多)映射 -->

<resultMap id="one2manyResultMap" type="shop">
 	<id property="shopId" column="shopid"/>
<result property="shopName" column="shopname"/>
<result property="shopAddress" column="shopaddress"/>
<!--
collection标签:用于关联子表(即one-to-many和many-to-many)。
ofType:property属性值对应集合中的具体类型(类的完全限定名或别名)。
-->
<collection property="products" ofType="product">
<result property="title" column="title"/>
</collection>
</resultMap>
 
<select id="one2many" resultMap="one2manyResultMap">
select s.shopid,shopname,shopaddress,title
from shop s inner join product p on s.shopid=p.shopid
</select>

 ________________________
<!-- many-to-many(多对多)映射 -->
<resultMap id="many2manyResultMap" type="customer">
<result property="customerName" column="customerName"/>

<collection property="ordersList" ofType="orders">
<id property="ordersId" column="ordersid"/>
<result property="ordersDate" column="ordersdate"/>

<collection property="ordersDetailList" ofType="ordersdetail">
<result property="quantity" column="quantity"/>
<association property="product" javaType="product">
<result property="title" column="title"/>
<result property="currentPrice" column="currentprice"/>
</association>
</collection>
</collection>
</resultMap>
 
<select id="many2many" resultMap="many2manyResultMap">
select customername,o.ordersid,to_char(ordersdate,'yyyy-mm-dd') ordersdate,
quantity,title,to_char(currentprice,'fm999990.0099') currentprice
from customer c inner join orders o on c.customerid=o.customerid
inner join ordersdetail od on o.ordersid=od.ordersid
inner join product p on od.productid=p.productid
</select>

15.查询缓存

Mybatis查询缓存:
提高程序响应速度,先从缓存中查找对应的数据,找到则直接从缓存中提取,若没找到则再去查询数据库。分为一级缓存(本地缓存)和二级缓存,一级缓存又称为SqlSession缓存,每个一级缓存都是独立存在且互不影响的,二级缓存又称为Mapper(映射器)缓存,二级缓存被每个一级缓存所共享。
 
一级缓存:默认支持,首次查询会将数据保存到一级缓存中,再次查询时会从一级缓存中去查找,前提是必须为同一个SqlSession对象,但在查询后若执行了提交(commit)或回滚(rollback)操作,则将会清空一级缓存,为了避免脏读。
 
二级缓存:需要通过配置开启,首次查询会将数据保存到二级缓存中,再次查询时会从二级缓存中去查找,
前提是可以不是同一个SqlSession对象,但必须是同一个Mapper对象(即namespace相同),但在查询后若执行了提交(commit)操作,则将会清空二级缓存,为了避免脏读。
开启二级缓存配置:
1.在SQL映射文件中添加配置:<cache/>
2.实体类实现序列化接口(Serializable):public class Shop implements Serializable
 
可在select标签中添加属性禁止使用二级缓存:
<select id="cache" resultType="shop" useCache="false">
select * from shop
</select>
 
flushCache:设置为true将会清空一级(本地)缓存和二级缓存,insert、delete和update操作默认为true,select操作默认为false。
<select id="cache" resultType="shop" flushCache="true">
select * from shop
</select>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值