zoukankan      html  css  js  c++  java
  • [Re] MyBatis-2(动态SQL+缓存+SSM整合+MBG)

    动态 SQL

    如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

    • 动态 SQL 是 MyBatis 强大特性之一。极大的简化我们拼装 SQL 的操作。
    • 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。
    • MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作。

    if、where

    <!-- List<Teacher> getTeacherByConditions(Teacher teacher); -->
    <select id="getTeacherByConditions" resultMap="teacherMap">
        SELECT * FROM teacher
        <!-- <where>可以删除前面多余的 AND:SQL 查询条件的 AND 一定要写前面 -->
        <!-- <bind> 可以将 OGNL 表达式的值绑定到一个变量中,方便后来引用这个变量的值(没用) -->
        <bind name="_tname" value="'%'+tname+'%'">
        <where>
            <!-- ↓ 判断条件,取出传入的JavaBean的属性,判断其是否为空 -->
            <if test="tname!=null">
                AND id > #{_tname}
            </if>
            <if test="subject!=null &amp;&amp; !subject.equals(&quot;&quot;)">
                AND subject LIKE #{subject}
            </if>
            <if test="birthday!=null">
                AND birth_date &lt; #{birthday}
            </if>
        </where>
    </select>
    

    trim、sql (include)

    <!-- 抽取可重用 SQL -->
    <sql id="selectTeacher">SELECT * FROM teacher</sql>
    
    <!-- List<Teacher> getTeacherByConditions(Teacher teacher); -->
    <select id="getTeacherByConditions" resultMap="teacherMap">
        <!--引用可重用 SQL-->
        <include refid="selectTeacher"></include>
        <!-- <trim> 自定义字符串截取规则
            prefix: 添加一个前缀
            suffix: 添加一个后缀
            prefixOverrides: 如果字符串开头为指定值,则去除
            suffixOverrides: 如果字符串尾部为指定值,则去除
        -->
        <trim prefix="WHERE" suffixOverrides="AND">
            <if test="tid!=null">
                id > #{tid} AND
            </if>
            <if test="subject!=null &amp;&amp; !subject.equals(&quot;&quot;)">
                subject LIKE #{subject} AND
            </if>
            <if test="birthday!=null">
                birth_date &lt; #{birthday} AND
            </if>
        </trim>
    </select>
    

    choose (when, otherwise)

    <!-- List<Teacher> getTeacherByOneCondition(Teacher teacher) -->
    <select id="getTeacherByOneCondition" resultMap="teacherMap">
        SELECT * FROM teacher
        <where>
        <choose>
            <when test="tid!=null">
                id > #{tid}
            </when>
            <when test="subject!=null &amp;&amp; !subject.equals(&quot;&quot;)">
                subject LIKE #{subject}
            </when>
            <when test="birthday!=null">
                birth_date &lt; #{birthday}
            </when>
            <otherwise>1=1</otherwise>
        </choose>
        </where>
    </select>
    

    set

    <!--
    // 带哪些字段,更新哪些字段 → 致使 @ModelAttribute 无使用场景
    public int updateTeacher(Teacher teacher);
     -->
    <update id="updateTeacher">
        UPDATE teacher
        <!--  UPDATE teacher SET <trim suffix="WHERE" suffixOverrides=","> -->
        <!-- set 去除末尾多余的',' -->
        <set>
            <if test="tname!=null &amp;&amp; !tname.equals(&quot;&quot;)">
                tname=#{tname},
            </if>
    
            <if test="subject!=null &amp;&amp; !subject.equals(&quot;&quot;)">
                subject=#{subject},
            </if>
    
            <if test="address!=null &amp;&amp; !address.equals(&quot;&quot;)">
                address=#{address},
            </if>
    
            <if test="birthday!=null">
                birth_date=#{birthday},
            </if>
        </set>
        <where>
            tid = #{tid}
        </where>
    </update>
    

    foreach

    动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。

    <!-- List<Teacher> getTeacherByIdIn(List<Integer> ids) -->
    <select id="getTeacherByIdIn" resultMap="teacherMap">
        SELECT * FROM teacher WHERE tid IN
        <!--
        collection="" 要遍历的集合
            遍历的是 List:
            > index 保存当前索引
            > item 将当前遍历出的元素赋值给指定的变量
            遍历的是 Map:
            > index 指定的变量就是保存当前遍历的 entry 的 key
            > item 指定的变量保存当前遍历的 entry 的 value
        ·······················
        separator="" 元素之间的分隔符
        open="" 以什么开始
        close="" 以什么结束
        -->
        <if test="ids.size > 0">
            <foreach collection="list" separator="," index="" item="id" open="(" close=")">
                #{id}
            </foreach>
        </if>
    </select>
    
    <!-- void addTeachers(@Param("teachers") List<Teacher> teachers) -->
    <insert id="addTeachers">
        INSERT INTO teacher(tname, subject) VALUES
        <foreach collection="teachers" separator="," item="teacher">
            (#{teacher.tname}, #{teacher.subject})
        </foreach>
    </insert>
    
    <!--
    MYSQL:
        除了将 VALUES 后的语句循环执行外,还可以将整条 SQL 语句都放入循环体中,语句末尾用';'
        除此之外,连接 DB 的 url 末尾还必须要增添一个连接属性:allowMultiQueries=true
    Oracle: 多条插入 SQL 要放在 begin...end; 中
     -->
    

    OGNL

    在 MyBatis 中,传入的参数可以用来做判断,额外的还有两个内置参数:
        _parameter:
            若传入了单个参数,就代表这个参数
            若传入了多个参数,就代表这多个参数封装起来的Map
        _databaseId: 如果配置了 databaseIdProvider,则该参数代表当前环境
            <if test="_databaseId == 'mysql'"> ... </if>
            <if test="_databaseId == 'oracle'"> ... </if>
    

    缓存机制

    缓存:暂时存储一些数据,可以极大的提升查询效率。MyBatis 系统中默认定义了两级缓存。

    • 一级缓存:线程级别的缓存;基于 SqlSession 级别的,也称为本地缓存;默认开启
    • 二级缓存:全局范围的缓存;基于 namespace 级别的缓存。除过当前线程的 SqlSession 能用外,其他也可以二级缓存。需要手动开启和配置

    一级缓存

    简述

    • 一级缓存(local cache),即本地缓存,作用域默认为 SqlSession。当 Session flush 或 close 后,该 Session 中的所有 Cache 将被清空。
    • 本地缓存不能被关闭,但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作用域。
    • 在 Mybatis 3.1 之后,可以配置本地缓存的作用域(在 mybatis.xml 中配置)

    演示

    @Test
    public void test() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher1 = mapper.getTeacherByTid(1);
        System.out.println(teacher1);
        Teacher teacher2 = mapper.getTeacherByTid(1);
        System.out.println(teacher2);
        System.out.println(teacher1 == teacher2); // true
    }
    

    同一次会话期间只要查询过的数据都会保存在当前 SqlSession 的一个 HashMap 中。

    失效情况

    每次查询,先看一级缓存(SqlSession 级别的缓存) 中有没有,如果没有再去发新的 SQL。

    1. 不同的 SqlSession,使用不同的一级缓存;只有在同一个 SqlSession 期间查询到的数据会保存在这个 SqlSession 的缓存中;下次这个 SqlSession 再去查询会先在它自己的缓存中去找。
    2. 同一条 SQL 语句,但是参数不同,就会导致 key 有变化,所以还会发新的 SQL
    3. 在这个 SqlSession 执行期间执行任何一次增删改操作,都会致使缓存被清空
    4. 同一个 SqlSession 两次查询期间手动清空了缓存

    源码

    public class PerpetualCache implements Cache {
    
      private String id;
    
      // 底层就是一个 Map
      private Map<Object, Object> cache = new HashMap<Object, Object>();
    
      public PerpetualCache(String id) {
        this.id = id;
      }
    
      @Override
      public String getId() {
        return id;
      }
    
      @Override
      public int getSize() {
        return cache.size();
      }
    
      @Override
      public void putObject(Object key, Object value) {
        cache.put(key, value);
      }
    
      @Override
      public Object getObject(Object key) {
        return cache.get(key);
      }
    
      @Override
      public Object removeObject(Object key) {
        return cache.remove(key);
      }
    
      @Override
      public void clear() {
        cache.clear();
      }
    
      @Override
      public ReadWriteLock getReadWriteLock() {
        return null;
      }
    
      @Override
      public boolean equals(Object o) {
        if (getId() == null) {
          throw new CacheException("Cache instances require an ID.");
        }
        if (this == o) {
          return true;
        }
        if (!(o instanceof Cache)) {
          return false;
        }
    
        Cache otherCache = (Cache) o;
        return getId().equals(otherCache.getId());
      }
    
      @Override
      public int hashCode() {
        if (getId() == null) {
          throw new CacheException("Cache instances require an ID.");
        }
        return getId().hashCode();
      }
    
    }
    

    BaseExecutor

    @SuppressWarnings("unchecked")
    @Override
    public <E> List<E> query(MappedStatement ms, Object parameter
            , RowBounds rowBounds, ResultHandler resultHandler
            , CacheKey key, BoundSql boundSql) throws SQLException {
        ErrorContext.instance().resource(ms.getResource())
                .activity("executing a query").object(ms.getId());
        if (closed) {
          throw new ExecutorException("Executor was closed.");
        }
        if (queryStack == 0 && ms.isFlushCacheRequired()) {
          clearLocalCache();
        }
        List<E> list;
        try {
          queryStack++;
          // 缓存中有没有
          list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
          if (list != null) { // 有
            handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
          } else { // 没有
            list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
          }
        } finally {
          queryStack--;
        }
        if (queryStack == 0) {
          for (DeferredLoad deferredLoad : deferredLoads) {
            deferredLoad.load();
          }
          // issue #601
          deferredLoads.clear();
          if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
            // issue #482
            clearLocalCache();
          }
        }
        return list;
    }
    

    二级缓存

    简述

    • 二级缓存(second level cache),全局作用域缓存
    • MyBatis 提供二级缓存的接口以及实现,缓存实现要求 POJO 实现 Serializable 接口
    • 二级缓存在 SqlSession 关闭或提交之后才会生效 → 这也就意味着不可能会出现一级缓存和二级缓存中有同一个数据!
      • 二级缓存中:不关就会一直放在一级缓存;只有一级缓存关闭,数据才会被迁移至二级缓存
      • 一级缓存中:二级缓存中没有此数据,就会看一级缓存,一级缓存中没有就会去查 DB。DB 的查询结果放在一级缓存中了
      • 任何时候都是先看二级缓存,再看一级缓存

    原理

    二级缓存基于 namespace。没有配置 <cache> 的 Mapper.xml 就没有二级缓存。并且,在二级缓存中,不同 Mapper 的数据都是存放在各自的 Map 中。

    缓存相关属性

    • eviction="LRU" 缓存回收策略
      • LRU – 最近最少使用的:移除最长时间不被使用的对象。
      • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
      • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
      • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    • flushInterval 刷新间隔
      • 单位毫秒
      • 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
    • size:引用数目
      • 正整数
      • 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
    • readOnly:只读
      • true:只读缓存;会给所有调用者返回缓存对象的引用。因此这些对象不能被修改。这提供了很重要的性能优势。
      • false:读写缓存;会返回缓存对象的拷贝(通过反序列化)。这会慢一些,但是安全,因此默认是 false。

    缓存有关设置

    1. 全局 setting 的 cacheEnable:配置二级缓存的开关
      <setting name="cacheEnabled" value="true"/>
      
    2. <select> 的 useCache 属性:配置这个 select 是否使用二级缓存 (一级缓存一直是使用的)
    3. 增删改标签的 flushCache 属性:增删改默认 flushCache=true,查询默认 flushCache=false。SQL 执行以后,会同时清空一级和二级缓存
    4. sqlSession.clearCache() 只是用来清除一级缓存
    5. 当在某一个作用域 (一级缓存Session/二级缓存Namespaces) 进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

    整合第三方缓存

    • MyBatis 定义了 Cache 接口方便我们进行自定义扩展。
    • EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider。
    • EhCache 使用步骤
      • 导入 ehcache 包,以及整合包,日志包
        ehcache-core-2.6.8.jar (ehcache 核心包)
        mybatis-ehcache-1.0.3.jar (ehcache 整合包)
        slf4j-api-1.6.1.jar
        slf4j-log4j12-1.6.2.jar
        
      • 编写 ehcache.xml 配置文件
        <?xml version="1.0" encoding="UTF-8"?>
        <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
            <!-- 磁盘保存路径 -->
            <diskStore path="U:ehcache" />
            <defaultCache
                maxElementsInMemory="3000"
                maxElementsOnDisk="10000000"
                eternal="false"
                overflowToDisk="true"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
            </defaultCache>
        </ehcache>
        
      • 在 Mapper.xml 中配置 cache 标签
        <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
        
    • Tips
      • POJO 可以不用实现 Serializable 接口
      • 参照缓存:若想在命名空间中共享相同的缓存配置和实例。可用 <cache-ref> 来引用另外一个缓存。
        <cache-ref namespace="cn.edu.nuist.mapper.TeacherMapper" />
        

    SSM 整合

    导包

    Spring

    [AOP核心]
        com.springsource.net.sf.cglib-2.2.0.jar
        com.springsource.org.aopalliance-1.0.0.jar
        com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
        spring-aspects-4.0.0.RELEASE.jar
    
    [IOC核心]
        commons-logging-1.1.3.jar
        spring-aop-4.0.0.RELEASE.jar
        spring-beans-4.0.0.RELEASE.jar
        spring-context-4.0.0.RELEASE.jar
        spring-core-4.0.0.RELEASE.jar
        spring-expression-4.0.0.RELEASE.jar
    
    [JDBC核心]
        spring-jdbc-4.0.0.RELEASE.jar
        spring-orm-4.0.0.RELEASE.jar
        spring-tx-4.0.0.RELEASE.jar
    

    SpringMVC

    [Ajax]
        jackson-annotations-2.1.5.jar
        jackson-core-2.1.5.jar
        jackson-databind-2.1.5.jar
    
    [数据校验]
        hibernate-validator-5.0.0.CR2.jar
        hibernate-validator-annotation-processor-5.0.0.CR2.jar
        classmate-0.8.0.jar
        jboss-logging-3.1.1.GA.jar
        validation-api-1.1.0.CR1.jar
    
    [上传下载]
        commons-fileupload-1.2.1.jar
        commons-io-2.0.jar
    
    [jstl]
        jstl.jar
        standard.jar
    
    [SpringMVC核心]
        spring-web-4.0.0.RELEASE.jar
        spring-webmvc-4.0.0.RELEASE.jar
    

    MyBatis

    [MyBatis核心]
        mybatis-3.4.1.jar
        mybatis-spring-1.3.0.jar
    
    [ehcache整合]
        ehcache-core-2.6.8.jar
        mybatis-ehcache-1.0.3.jar
        log4j-1.2.17.jar
        slf4j-api-1.7.21.jar
        slf4j-log4j12-1.7.21.jar
    

    database

    mysql-connector-java-5.1.37-bin.jar
    c3p0-0.9.1.2.jar
    

    写配置

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app ...>
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    
        <!-- 编码过滤器 -->
        <filter>
            <filter-name>CharacterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>utf-8</param-value>
            </init-param>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>CharacterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <!-- REST 过滤器 -->
        <filter>
            <filter-name>HiddenHttpMethodFilter</filter-name>
            <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>HiddenHttpMethodFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <!-- 配置 spring 容器启动 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/applicationContext.xml</param-value>
        </context-param>
    
        <!-- Bootstraps the root web application context before servlet initialization -->
        <listener>
            <listener-class>
                org.springframework.web.context.ContextLoaderListener
            </listener-class>
        </listener>
    
        <!-- 配置 SpringMVC 前端控制器 -->
        <servlet>
            <servlet-name>springDispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/applicationContext-mvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!-- Map all requests to the DispatcherServlet for handling -->
        <servlet-mapping>
            <servlet-name>springDispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    

    SpringMVC 配置文件

    applicationContext-mvc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans ...>
        <context:component-scan base-package="cn.edu.nuist" use-default-filters="false">
        <context:include-filter type="annotation"
                expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    
        <!-- 文件上传解析器 -->
        <bean id="multipartResolver"
                class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="defaultEncoding" value="UTF-8"></property>
            <property name="maxUploadSize" value="#{1024*1024*20}"></property>
        </bean>
    
        <!-- 扫静态 -->
        <mvc:default-servlet-handler/>
        <!-- 扫动态 -->
        <mvc:annotation-driven></mvc:annotation-driven>
    </beans>
    

    Spring 配置文件

    applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans ...>
        <!-- 1. 包扫描 -->
        <context:component-scan base-package="cn.edu.nuist">
            <context:exclude-filter type="annotation"
                    expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    
        <!-- 2. 导入外部配置文件 -->
        <context:property-placeholder location="classpath:dbconfig.properties"/>
    
        <!-- 3. 配数据源 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driverClass}"/>
            <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
            <property name="user" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
            <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
            <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
        </bean>
    
        <!-- 4. 整合 MyBatis !!! -->
        <!-- 4.1 根据配置文件,生产 SqlSessionFactory 的工厂 bean -->
        <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 指定 MyBatis 全局配置文件的位置 -->
            <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
            <!-- 引用 Spring 创建的数据源 (事务控制是 Spring 在做) -->
            <property name="dataSource" ref="dataSource"></property>
            <!-- 指定 Mapper 映射文件的位置 -->
            <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>
        </bean>
    
        <!-- 4.2 会查找类路径下的 Mapper<I>[映射器],并自动将它们创建成 MapperFactoryBean -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!-- 为映射器接口文件设置基本的包路径,每个映射器将会在指定的包路径中递归地被搜索到 -->
            <property name="basePackage" value="cn.edu.nuist.mapper"></property>
        </bean>
        <!-- <mybatis-spring:scan base-package="cn.edu.nuist.mapper"> -->
    
        <!-- 5. [事务控制] 配置事务管理器,让其控制数据源中连接的关闭和提交 -->
        <bean id="transactionManager"
                class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
        <!-- 6. 基于 XML 配置事务,详见 [Re:Spring-2]#7.6 -->
        <aop:config>
            <!-- 配置切入点表达式((哪些方法切入事务) -->
            <aop:pointcut expression="execution(* cn.edu.nuist.service.*.*(..))" id="txPoint"/>
            <aop:advisor advice-ref="myTx" pointcut-ref="txPoint"/>
        </aop:config>
    
        <!-- 7. 事务增强(属性)-->
        <tx:advice id="myTx" transaction-manager="transactionManager">
            <!-- 配置事务属性 -->
            <tx:attributes>
                <tx:method name="*" rollback-for="java.lang.Exception"/>
                <tx:method name="get*" read-only="true"/>
            </tx:attributes>
        </tx:advice>
    </beans>
    
    public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T>
    
    1. MapperFactoryBean 创建的代理类实现了 Mapper<I>,并且注入到应用程序中。因为代理创建在运行时环境中(Runtime),那么指定的映射器必须是一个接口,而不是一个具体的实现类。
    2. 数据映射器 Mapper<I> 不需要显示写一个注解交给 Spring 管理,然后在 Service 层进行注入。因为 Mapper<I> 其实是供 MapperFactoryBean 创建的代理类来实现的,然后自动放到 Spring 的 IOC 容器中,在 Service 实现中注入的是 MapperFactoryBean 创建的代理类。

    https://www.cnblogs.com/Joe-Go/p/10256241.html
    https://www.cnblogs.com/xiaolang8762400/p/7399274.html

    mybatis 配置文件

    <?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>
        <plugins>
            <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
        </plugins>
    </configuration>
    

    其他配置文件

    dbconfig.properties

    jdbc.user=root
    jdbc.password=root
    jdbc.jdbcUrl=jdbc:mysql:///test
    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.maxPoolSize=100
    jdbc.minPoolSize=10
    

    测试

    MBG

    MyBatis Generator,简称 MBG,是一个专门为 MyBatis 框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件、接口以及 bean 类。支持基本的增删改查,以及 QBC 风格的条件查询。但是表连接、存储过程等这些复杂 SQL 的定义需要我们手工编写。

    mybatis-generator-core-1.3.2.jar

    MBG 配置文件

    • javaModelGenerator 配置 JavaBean 的生成策略
    • sqlMapGenerator 配置 SQL 映射文件的生成策略
    • javaClientGenerator 配置 Mapper 接口的生成策略
    • table 配置要逆向解析的数据表
      • tableName:表名
      • domainObjectName:对应的 JavaBean 名字
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
      PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
      "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    
    <generatorConfiguration>
        <!--
        targetRuntime
            MyBatis3Simple:基础版 CRUD
            MyBatis3:复杂版(带动态 SQL) CRUD
         -->
        <context id="DB2Tables" targetRuntime="MyBatis3">
            <commentGenerator>
                <property name="suppressAllComments" value="true"/>
            </commentGenerator>
    
            <!-- jdbcConnection:指导连接到哪个数据库 -->
            <jdbcConnection
                    driverClass="com.mysql.jdbc.Driver"
                    connectionURL="jdbc:mysql:///test"
                    userId="root"
                    password="root">
            </jdbcConnection>
    
            <javaTypeResolver>
                <property name="forceBigDecimals" value="false" />
            </javaTypeResolver>
    
            <!--
            javaModelGenerator:生成 POJO
                targetPackage:生成的 POJO 放在哪个包
                targetProject:放在哪个工程下
            -->
            <javaModelGenerator
                    targetPackage="cn.edu.nuist.bean"
                    targetProject=".src">
                <property name="enableSubPackages" value="true" />
                <property name="trimStrings" value="true" />
            </javaModelGenerator>
    
            <!--sqlMapGenerator:SQL 映射文件生成器;指定映射文件生成的地方  -->
            <sqlMapGenerator
                    targetPackage="cn.edu.nuist.mapper"
                    targetProject=".conf">
                <property name="enableSubPackages" value="true" />
            </sqlMapGenerator>
    
            <!-- javaClientGenerator:Mapper<I> 生成的地方 -->
            <javaClientGenerator type="XMLMAPPER"
                    targetPackage="cn.edu.nuist.mapper"
                    targetProject=".src">
                <property name="enableSubPackages" value="true" />
            </javaClientGenerator>
    
            <!--
            table:指定要逆向生成哪个数据表
                tableName="t_cat":表名
                domainObjectName="":这个表对应的对象名
            -->
            <table tableName="teacher" domainObjectName="Teacher"></table>
            <table tableName="emp" domainObjectName="Employee"></table>
            <table tableName="dept" domainObjectName="Department"></table>
        </context>
    </generatorConfiguration>
    

    运行代码生成器生成代码

    public class TestMBG {
        public static void main(String[] args) throws Exception {
            List<String> warnings = new ArrayList<String>();
            boolean overwrite = true;
            File configFile = new File("mbg.xml");
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config = cp.parseConfiguration(configFile);
            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator
                    = new MyBatisGenerator(config, callback, warnings);
            // 代码生成
            myBatisGenerator.generate(null);
            System.out.println("生成了!");
        }
    }
    
  • 相关阅读:
    前端经典书籍
    D3基本概念
    Array.map和parseInt的用法
    首屏和白屏时间计算
    css换肤总结
    文件上传总结
    js的uuid
    html5 drag事件用法
    shell脚本中的逻辑判断 文件目录属性判断 if特殊用法 case判断
    Mac vim“装逼”配置
  • 原文地址:https://www.cnblogs.com/liujiaqi1101/p/13696918.html
Copyright © 2011-2022 走看看