3.9.11. MyBatis 集成

MyBatis 框架,与 ORM 本地查询QueryRunner相比,提供了更广泛的执行 SQL 和将查询结果映射到对象的功能。

按照下面的步骤在 CUBA 项目中集成 MyBatis。

  1. core 模块的根 java 包创建处理 UUID 类型的类。

    1. import com.haulmont.cuba.core.global.UuidProvider;
    2. import org.apache.ibatis.type.JdbcType;
    3. import org.apache.ibatis.type.TypeHandler;
    4. import java.sql.*;
    5. public class UUIDTypeHandler implements TypeHandler {
    6. @Override
    7. public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
    8. ps.setObject(i, parameter, Types.OTHER);
    9. }
    10. @Override
    11. public Object getResult(ResultSet rs, String columnName) throws SQLException {
    12. String val = rs.getString(columnName);
    13. if (val != null) {
    14. return UuidProvider.fromString(val);
    15. } else {
    16. return null;
    17. }
    18. }
    19. @Override
    20. public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
    21. String val = rs.getString(columnIndex);
    22. if (val != null) {
    23. return UuidProvider.fromString(val);
    24. } else {
    25. return null;
    26. }
    27. }
    28. @Override
    29. public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
    30. String val = cs.getString(columnIndex);
    31. if (val != null) {
    32. return UuidProvider.fromString(val);
    33. } else {
    34. return null;
    35. }
    36. }
    37. }
  2. core 模块的 spring.xml 文件所在目录创建 mybatis.xml 配置文件,在文件内正确引用 UUIDTypeHandler

    1. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    2. <configuration>
    3. <settings>
    4. <setting name="lazyLoadingEnabled" value="false"/>
    5. </settings>
    6. <typeHandlers>
    7. <typeHandler javaType="java.util.UUID"
    8. handler="com.company.demo.core.UUIDTypeHandler"/>
    9. </typeHandlers>
    10. </configuration>
  3. 将下面的 bean 都添加到 spring.xml 文件以便在项目中使用 MyBatis:

    1. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    2. <property name="dataSource" ref="cubaDataSource"/>
    3. <property name="configLocation" value="com/company/demo/mybatis.xml"/>
    4. <property name="mapperLocations" value="com/company/demo/core/sqlmap/*.xml"/>
    5. </bean>
    6. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    7. <property name="basePackage" value="com/company/demo.core.dao"/>
    8. <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    9. </bean>
    10. <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    11. <constructor-arg index="0" ref="sqlSessionFactory" />
    12. </bean>

    sqlSessionFactory bean 包含了指向 mybatis.xml 的引用。

    MapperLocations 参数定义了 mapperLocations 映射文件的路径(根据 Spring 中 ResourceLoader 接口的资源解析规则)。

  4. 最后,在 build.gradle 中的 core 模块添加 MyBatis 的依赖:

    1. compile('org.mybatis:mybatis:3.2.8')
    2. compile('org.mybatis:mybatis-spring:1.2.5')

下面是一个映射文件的示例,用于加载 订单(Order) 的实例以及相关的 客户(Customer)订单商品(order item) 集合:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.sample.sales">
  4. <select id="selectOrder" resultMap="orderResultMap">
  5. select
  6. o.ID as order_id,
  7. o.DATE as order_date,
  8. o.AMOUNT as order_amount,
  9. c.ID as customer_id,
  10. c.NAME as customer_name,
  11. c.EMAIL as customer_email,
  12. i.ID as item_id,
  13. i.QUANTITY as item_quantity,
  14. p.ID as product_id,
  15. p.NAME as product_name
  16. from
  17. SALES_ORDER o
  18. left join SALES_CUSTOMER c on c.ID = o.CUSTOMER_ID
  19. left join SALES_ITEM i on i.ORDER_ID = o.id and i.DELETE_TS is null
  20. left join SALES_PRODUCT p on p.ID = i.PRODUCT_ID
  21. where
  22. c.id = #{id}
  23. </select>
  24. <resultMap id="orderResultMap" type="com.sample.sales.entity.Order">
  25. <id property="id" column="order_id"/>
  26. <result property="date" column="order_date"/>
  27. <result property="amount" column="order_amount"/>
  28. <association property="customer" column="customer_id" javaType="com.sample.sales.entity.Customer">
  29. <id property="id" column="customer_id"/>
  30. <result property="name" column="customer_name"/>
  31. <result property="email" column="customer_email"/>
  32. </association>
  33. <collection property="items" ofType="com.sample.sales.entity.Item">
  34. <id property="id" column="item_id"/>
  35. <result property="quantity" column="item_quantity"/>
  36. <association property="product" column="product_id" javaType="com.sample.sales.entity.Product">
  37. <id property="id" column="product_id"/>
  38. <result property="name" column="product_name"/>
  39. </association>
  40. </collection>
  41. </resultMap>
  42. </mapper>

以下代码可用于获取上面示例中的查询结果:

  1. try (Transaction tx = persistence.createTransaction()) {
  2. SqlSession sqlSession = AppBeans.get("sqlSession");
  3. Order order = (Order) sqlSession.selectOne("com.sample.sales.selectOrder", orderId);
  4. tx.commit();