关于mybatis是什么、有什么特点、实现机制之类的话题,网上通篇大论,这里不再赘述,只谈干货,希望能够用最高的效率,最精确的和读者找到共鸣并相互交流。
一、为什么要使用mybaits框架?
1)效率上最优:相比hibernate而言,mybatis的体积如同九牛一毛,加载速度快,运行速度快,极大的提供和程序和数据库之间的交互效率;
2)灵活性最强:mybatis框架的实现是基于开发者对SQL语句的使用,因此开发者可以非常灵活的对SQL语句进行编写和修改已到达需要的结果;
3)学习性强:通过对mybaits框架的时候,开发者可以更好更多的结合数据库进行SQL语句的编写,在完成功能开发的同时也进一步练习和提高了对数据库常用技术的使用,可谓一石二鸟。
二、mybatis在项目中扮演什么角色?以什么形式存在?mybatis的事物管理机制是怎样的?
1)mybatis是一个ORM框架,属于DAO层,负责和数据库进行交互;
2)DAO层文件夹中分别存放了mapper.java 和 mapper.xml ;
3)mapper.xml 是对 mapper.java 接口的实现。他们之间的关联通过mapper.xml 中的<mapper ></mapper> 标签中的namespace属性实现绑定
- <?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="mapper.OrderitemMapper" >
- </mapper>
4)检验是否绑定成功:如果按住ctrl键点击namespace中的值,可以直接跳转到对应的接口,则表示跳转成功
5)mybatis框架独立运行时,需要手动控制事物,进行打开、提交、回滚、关闭操作。若集成了Spring框架,则可以将其托管到Spring中自动管理
- SqlSession session= MyBatisSessionFactory.getSession();
- session.commit();
- session.rollback();
- session.close();
三、mybaits接口方法和接口方法的实现
1)mapper.xml 是 mapper.java 的实现,两者通过 <statementSql></statementSql> 的 id属性来关联 【statementSql 泛指xml文件中的sql执行语句片段】
mapper.java
- package mapper;
-
- import java.util.List;
-
- import pojo.CustomerAndOrder;
-
- public interface CustomerMapperOrder {
- List<CustomerAndOrder> findCusAndOrderByCid ();
- }
mapper.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="mapper.CustomerMapperOrder" >
-
- <sql id="cusAndOrder">
- c.*,
- o.order_id as orderId,
- o.create_date as createDate
- </sql>
-
- <select id="findCusAndOrderByCid" resultType="pojo.CustomerAndOrder">
- select
- <include refid="cusAndOrder"/>
- from
- customer c,ordertable o
- WHERE
- c.cid = o.cid
- </select>
- </mapper>
可以看到<select id = " finCusAndOrderByCid" > 中 id 的值 就是 mapper.java 中的方法名
四、接口方法和接口实现中 出入参 类型的定义
1)接口实现中可用的类型:java中的普通类型 和 自定义的pojo类型
2)定义入参的的属性:在 parameterType = " " 属性中定义【注意:入参是可选属性,根据需求设定】
- <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" >
- select
- <include refid="Base_Column_List" />
- from product
- where product_id = #{productId,jdbcType=VARCHAR}
- </select>
3)定义出参的属性:出参定义的是mapper.xml中的重点。
对于增删改语句,返回值是可选参数,如果要求有返回值,则他们的返回值默认为 int 型,这是由mybatis的底层定义的
如:mapper.xml
- <delete id="deleteByPrimaryKey" parameterType="java.lang.String" >
- delete from product
- where product_id = #{productId,jdbcType=VARCHAR}
- </delete>
-
- <insert id="insert" parameterType="pojo.Product" >
- insert into product (product_id, product_factroy, product_store,
- product_descript)
- values (#{productId,jdbcType=VARCHAR}, #{productFactroy,jdbcType=VARCHAR}, #{productStore,jdbcType=INTEGER},
- #{productDescript,jdbcType=VARCHAR})
- </insert>
- <pre name="code" class="html"><update id="updateByPrimaryKey" parameterType="pojo.Product" >
- update product
- set product_factroy = #{productFactroy,jdbcType=VARCHAR},
- product_store = #{productStore,jdbcType=INTEGER},
- product_descript = #{productDescript,jdbcType=VARCHAR}
- where product_id = #{productId,jdbcType=VARCHAR}
- </update>
mapper.java
- int deleteByPrimaryKey(String productId) throws Exception;
-
- int insert(Product record) throws Exception ;
-
- int updateByPrimaryKey(Product record) throws Exception;
而对于查询语句<select > 而言,返回值是查询语句得到每一条
结果的映射。
查询结果的数据类型,决定了出参的类型;查询结果的条目数,决定了是否采用集合或者数组。换言之:如果返回单个值,外部用单值的方式接收;如果是多个值,就需要用List<?> 来接收
mapper.java
-
- Product selectByPrimaryKey(String productId) throws Exception;
-
-
- List<Product> selectProByConditions(Product product);
mapper.xml 【在xml中的返回值类型为pojo.Product ,返回值的条目数决定了外部接收的单个值类型还是多个值类型】
- <select id="selectByPrimaryKey" resultMap="pojo.Product" parameterType="java.lang.String" >
- select
- <include refid="Base_Column_List" />
- from product
- where product_id = #{productId,jdbcType=VARCHAR}
- </select>
-
- <select id="selectProByConditions" parameterType="<span style="font-family:Arial, Helvetica, sans-serif;">java.lang.String</span>" resultMap="pojo.Product">
- select * from product
- <where>
- <if test="productId!=null and productId!=''">
- and product_id = #{productId}
- </if>
- <if test="productFactroy!=null and productFactroy!='' ">
- and product_factroy = #{productFactroy}
- </if>
- <if test="productStore!=null">
- and product_store = #{productStore}
- </if>
- <if test="productDescript!=null">
- and product_descript = #{productDescript}
- </if>
- </where>
- </select>
管理结果映射的标签有两种,分别是resultType和 resultMap 。通过这两个标签建立数据库查询结果的列和程序中实体类或java类型的映射关系
resultType 和 resultMap 之间的关系和区别,一直是mybatis开发者关心的问题。但其实通过几个小的练习,就可以将两者的关系和使用场景搞明白了。
resultType:是属性,可以管理普通返回值类型,也可以返回自定义的pojo包装类。
如:
- <sql id="cusAndOrder">
- c.*,
- o.order_id as orderId,
- o.create_date as createDate
- </sql>
-
- <select id="findCusAndOrderByCid" resultType="pojo.CustomerAndOrder">
- select
- <include refid="cusAndOrder"/>
- from
- customer c,ordertable o
- WHERE
- c.cid = o.cid
- </select>
其中pojo.CustomerAndOrder是笔者自定义的类型,继承与Customer 类,并加入了几条Order的属性【注意:在声明自定义类时,一定要生成getter、setter、还有两构造方法 】
有了构造方法,对象才能被初始化,查询结果才能被映射到对应字段
- package pojo;
-
- import java.math.BigDecimal;
- import java.util.Date;
-
- public class CustomerAndOrder extends Customer {
-
- private String orderId;
-
- private Date createDate;
-
- public String getOrderId() {
- return orderId;
- }
-
- public void setOrderId(String orderId) {
- this.orderId = orderId;
- }
-
- public Date getCreateDate() {
- return createDate;
- }
-
- public void setCreateDate(Date createDate) {
- this.createDate = createDate;
- }
-
- public CustomerAndOrder(String cid, String cname, String address,
- String clevel, String email, BigDecimal balance, String orderId,
- Date createDate) {
- super(cid, cname, address, clevel, email, balance);
- this.orderId = orderId;
- this.createDate = createDate;
- }
-
- public CustomerAndOrder() {
- super();
-
- }
-
- public CustomerAndOrder(String cid, String cname, String address,
- String clevel, String email, BigDecimal balance) {
- super(cid, cname, address, clevel, email, balance);
-
- }
-
-
-
- }<strong>
- </strong>
操作技巧:通过resultType定义返回值的时候,一定要注意查询结果的列名和属性名要一致才能被映射到。如果列名和字段名不一致,可以通过对字段名起别名,将值映射到自定义的属性中
从上方的两段代码中可以发现<sql>片段中将order_id 起别名为 orderId 的目的就是为了映射关联
resultMap:是属性,也是标签;它可以定义返回值类型,也可以作为映射管理器标签独立存在
- <resultMap id="BaseResultMap" type="pojo.OrderTable" >
- <id column="order_id" property="orderId" jdbcType="VARCHAR" />
- <result column="cid" property="cid" jdbcType="VARCHAR" />
- <result column="address" property="address" jdbcType="VARCHAR" />
- <result column="create_date" property="createDate" jdbcType="TIMESTAMP" />
- <result column="orderitem_id" property="orderitemId" jdbcType="VARCHAR" />
-
- <collection property="orderitemList" ofType="pojo.Orderitem">
- <id column="orderitem_id" property="orderitemId"/>
- <result column="product_id" property="productId"/>
- <result column="count" property="count"/>
- </collection>
- </resultMap>
-
- lt;select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" >
- <!--
- WARNING - @mbggenerated
- This element is automatically generated by MyBatis Generator, do not modify.
- This element was generated on Fri May 06 15:49:42 CST 2016.
- -->
- select
- <include refid="Base_Column_List" />
- from ordertable
- where ordertable.order_id = #{orderId,jdbcType=VARCHAR}
- </select>
从上面的代码块中可以发现:resultMap 作为映射管理器标签独立使用 ,其中id属性的值作为映射管理器的标识码,可以被statementSql引用
而映射管理器的作用在于可以用来维护实体类之间的关系,如代码片段中所示:resultMap中通过<collection>标签维护了一个一对多的关系,在pojo.OrderTable中有一个以List存在的Orderitem 类,和OrderTable是一对多的关系。
resultMap作为映射管理器标签的具体功能将在《Mybatis 框架使用的最核心内容(二):mpper.xml中的常用标签详解》中介绍