The platform includes MyBatis framework, which offers wider capabilities for running SQL and mapping query results to objects compared to ORM native query or QueryRunner.
The following beans must be added into spring.xml file of the core module to use MyBatis in the project:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="cuba-mybatis.xml"/> <property name="mapperLocations" value="classpath*:com/sample/sales/core/sqlmap/*.xml"/> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean>
The MapperLocations parameter defines a path to mapperLocations
mapping files (according to the rules of ResourceLoader
Spring interface).
Below is the an example of a mapping file for loading an instance of Order
together with a related Customer
and a collection of Order
items:
<?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.sample.sales"> <select id="selectOrder" resultMap="orderResultMap"> select o.ID as order_id, o.DATE as order_date, o.AMOUNT as order_amount, c.ID as customer_id, c.NAME as customer_name, c.EMAIL as customer_email, i.ID as item_id, i.QUANTITY as item_quantity, p.ID as product_id, p.NAME as product_name from SALES_ORDER o left join SALES_CUSTOMER c on c.ID = o.CUSTOMER_ID left join SALES_ITEM i on i.ORDER_ID = o.id and i.DELETE_TS is null left join SALES_PRODUCT p on p.ID = i.PRODUCT_ID where c.id = #{id} </select> <resultMap id="orderResultMap" type="com.sample.sales.entity.Order"> <id property="id" column="order_id"/> <result property="date" column="order_date"/> <result property="amount" column="order_amount"/> <association property="customer" column="customer_id" javaType="com.sample.sales.entity.Customer"> <id property="id" column="customer_id"/> <result property="name" column="customer_name"/> <result property="email" column="customer_email"/> </association> <collection property="items" ofType="com.sample.sales.entity.Item"> <id property="id" column="item_id"/> <result property="quantity" column="item_quantity"/> <association property="product" column="product_id" javaType="com.sample.sales.entity.Product"> <id property="id" column="product_id"/> <result property="name" column="product_name"/> </association> </collection> </resultMap> </mapper>
The following code can be used to retrieve query results from the example above:
Transaction tx = persistence.createTransaction(); try { SqlSession sqlSession = AppBeans.get("sqlSession"); Order order = (Order) sqlSession.selectOne("com.sample.sales.selectOrder", orderId); tx.commit(); } finally { tx.end(); }
The objects loaded using MyBatis can be changed and sent to EntityManager.merge()
in order to be persisted to the database. However, only non-null
attributes will be persisted, i.e. if an attribute was not loaded or was intentionally set to null
, the corresponding database field will remain unchanged.
This behaviour is defined by the default openjpa.DetachState=loaded
ORM parameter.