zoukankan      html  css  js  c++  java
  • MyBatis 开发学习记录

    使用MyBatis时主要是完成POJO和SQL的映射规则

    MyBatis基本构成:

      SqlSessionFactoryBuilder

      SqlSessionFactory

      SqlSession

      SqlMapper(主要是定义参数类型,描述缓存,描述SQL语句,定义查询结果和POJO的映射关系)

    配置(<configuration>):

      <properties/>

        在<properties>中可以定义参数如数据库密码,用户名等形式如:

     <properties>
         <property name="driver" value="com.mysql.jdbc.Driver" />
         <property name="url" value="jdbc:mysql://localhost:3306/test" />
         <property name="username" value="root" />
         <property name="password" value="root" />
    </properties>

        然后以${name}方式可以引用

        此外可以直接引入properties文件,如:

    <properties resource="jdbc.properties"/>

      <settings/>用于开户mybatis的一些功能,常用的主要有如下:

    <settings>
          <!-- 该配置影响的所有映射器中配置的缓存的全局开关。默认值true -->  
          <setting name="cacheEnabled" value="true"/>  
          <!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。默认值false  -->  
          <setting name="lazyLoadingEnabled" value="true"/>  
          <!-- 将积极加载改为消息加载即按需加载 -->  
          <setting name="aggressiveLazyLoading" value="false"/>   
    </settings>    

      <typeAlases/>用法如下,另外注意的是MyBatis提供了很多的类型别名,一般直接使用的是封装类,如int其实是Integer,基本类型是_int:

        <!-- 设置别名 -->
        <typeAliases>
            <!-- type指的是javabean的完全限定名   alias就是指代别名-->
            <typeAlias alias="student" type="cn.entity.Student" />
        </typeAliases>

      <typeHandlers/>

      <objectFactory/>

      <plugins/>

      <environments>

        <enviroment>

          <transactionManager/>

          <dataSource/>

        <environment>

      </environments>

      environments的使用:

    <environments default="development">  
             <environment id="development">  
                 <transactionManager type="JDBC" />  
                 <!-- 配置数据库连接信息 -->  
                 <dataSource type="POOLED">  
                     <!-- value属性值引用db.properties配置文件中配置的值 -->  
                     <property name="driver" value="${driver}" />  
                     <property name="url" value="${url}" />  
                     <property name="username" value="${name}" />  
                     <property name="password" value="${password}" />  
                 </dataSource>  
             </environment>  
    </environments> 

    映射器:

      元素:select  insert  update  delete  sql  resultMap  cache

    <?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="com.m24.demo.dao.AppointmentMapper">
        <cache />
        
        <resultMap id="appointment" type="com.m24.demo.entity.Appointment">
            <id property="bookId" column="book_id"/>
            <id property="studentId" column="student_id"/>
            <result property="appointTime" column="appoint_time"/>
            <association property="book" column="book_id" select="com.m24.demo.dao.BookMapper.queryById" />
            <association property="student" column="student_id" select="com.m24.demo.dao.StudentMapper.queryById" />
        </resultMap>
        
        <insert id="insertAppointment">
            INSERT INTO appointment (book_id, student_id)
            VALUES (#{bookId}, #{studentId})
        </insert>
        
        <select id="queryWithStudentId" resultMap="appointment" useCache="true">
            SELECT
                a.book_id,
                a.student_id,
                a.appoint_time
            FROM
                appointment a
            INNER JOIN student b ON a.student_id = b.student_id
            WHERE
                a.student_id = #{studentId}
        </select>
    </mapper>

      主键回填(userGeneratedKey, keyProperty):

        <insert id="insertBook" parameterType="com.m24.demo.entity.Book" 
            useGeneratedKeys="true" keyProperty="bookId">
            INSERT ignore INTO book(book_name,book_number )
            VALUES (#{bookName},#{bookNumber})
        </insert>

      关联查询:

            <collection property="book" column="book_id" select="com.m24.demo.dao.BookMapper.queryById" />
            <association property="student" column="student_id" select="com.m24.demo.dao.StudentMapper.queryById" />

      参数传递时,可使用以下2种方法:

        1、参数自动映射,或配置POJO(列名和属性名不同时)

        2、使用注解@Param

    public interface AppointmentMapper {
        /**
        *
        * @param bookId
        * @param studentId
        * @return
        */
       int insertAppointment(@Param("bookId")long bookId,@Param("studentId")long studentId);
    
       /**
        * 
        * @param bookId
        * @return
        */
       Appointment queryWithStudentId(@Param("studentId")long studentId);
    }

      缓存 <cache/>,使用缓存时,POJO必须是可序列化的,默认下

        <cache eviction:="LRU" flushInterval="100000" size="1024" readOnly="true"/>

        select缓存,insert update delete 刷新缓存

      自定义缓存,实现org.apache.ibatis.cache.Cache接口,然后在<cache type="??"/>中指定type,

      CRUD中,可使用flushCache,useCache配置SQL层面的缓存规则

      注意:缓存和延迟加载不是同一个东西

    动态SQL:

      if:test测试

    <if test="var != null and var != '' "">
        ...
    </if>

      choose(when, otherwise):

    <choose>
        <when test="???">
            ...
        </when>
        <otherwise>
            ...
        </otherwise>
    </choose>

      trim(where, set):

    <trim prefix="语句前缀" suffixOverrides="要去掉的字串">
        ...
    </trim>

      foreach:

    <foreach item="sex" index="index" collection="sexList" open="(" seperator=";" close=")">
        #{sex}
    </foreach>

     MyBatis解析运行原理:

      1、读取配置文件缓存到Configuration对象,创建SqlSessionFactory

      2、执行SqlSession

      MyBatis中普遍使用反射技术:

    反射:
        JDK动态代理:
          1、编写服务类和接口,这个是真正的服务提供者,在JDK代理中接口是必须的
          2、编写代理类(InvocationHandler),提供绑定(Proxy.newProxyInstance)及代理方法invoke
        CGLIB动态代理:
        1、编写代理类MethodInterceptor,实现回调方法intercept
        2、指定父类enhancer.setSupperClass,设置回调方法enhancer.setCallback,动态创建子类enhancer.create

      有关反射详细:http://www.cnblogs.com/m2492565210/p/7250628.html

    SqlSession四大对象:

      Executor:执行器,由它调度StatementHandler(使用数据库Statement,PreparedStatement执行操作), ParameterHandler(参数处理), ResultHandler(数据集封装返回处理)

    插件:

      开发插件时,要实现Interceptor接口,实现里面的intercept plugin setProperties方法,然后在plugins注册

    使用例子
    1.写一个类,并且实现Interceptor接口
    2.在上述类使用@Intercepts注解,配置拦截信息
    3.在配置文件配置插件
    @Intercepts({ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
            RowBounds.class, ResultHandler.class }) })
    public class MyInterceptor implements Interceptor {
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            return invocation.proceed();
        }
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
        @Override
        public void setProperties(Properties properties) {
            // TODO Auto-generated method stub
    
        }
    }
    配置文件加入
    <plugins>
        <plugin interceptor="weber.mybatis.plugin.MyInterceptor" />
    </plugins>

    Spring-MyBatis:

       事务控制的2个点:隔离级别和传播行为

      隔离级别:

      脏读  不可重复读  幻读
    读未提交 Y Y Y
    读写提交 N Y Y
    可重复读 N N Y
    序列化 N N N

      传播行为:

          REQUIRED:业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务。

             NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。

             REQUIRESNEW:不管是否存在事务,该方法总汇为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。

             MANDATORY:该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出异常。

             SUPPORTS:该方法在某个事务范围内被调用,则方法成为该事务的一部分。如果方法在该事务范围外被调用,该方法就在没有事务的环境下执行。

             NEVER:该方法绝对不能在事务范围内执行。如果在就抛异常。只有该方法没有关联到任何事务,才正常执行。

             NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。 

    MyBatis默认使用Log4j记录日志,使用时应在classpath中配置log4j.properties文件

    MyBatis使用原始Dao和Mapper接口两种方法实现Dao,实现Dao时应该要注意SqlSession是线程不安全的,每个线程都应该有自己的实例,每个Session都应控制在一个请求或一个方法内,并在每次使用后要关闭Session(finally)

    使用原始Dao开发方式,需要编写Dao接口和对应的实现类及映射文件,Dao实现类通过SqlSession及sql.xml文件中的sql id完成数据库读写

    Mapper接口需要编写mapper接口和mapper文件,开发规范:

    mapper.xml文件中的namespace和mapper接口类路径相同

    mapper接口方法名和mapper.xml中定义的statement的id相同

    mapper接口输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同

    mapper接口输出参数类型和mapper.xml中定义的每个sql的resutType的类型相同

        

  • 相关阅读:
    最小路径
    零钱兑换
    硬币
    三步问题
    区域和检索
    除数博弈
    URI和URL的辨别
    交叉编译OpenMP
    牛客挑战赛44D-数列的和
    CF1408H. Rainbow Triples
  • 原文地址:https://www.cnblogs.com/m2492565210/p/7895947.html
Copyright © 2011-2022 走看看