|
注释信息已经包含在代码中,这里就不多做解释了。
参考资料:Mybatis参考资料
包含基本操作(基本篇)和spring事务管理以及懒加载(进阶篇)。
以及开发中常遇到的一对一,一对多情况的配置(collection/association)
首先是maven Dependency:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tch.test</groupId>
<artifactId>spring-mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-mybatis</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit-version>4.11</junit-version>
<spring-version>3.2.6.RELEASE</spring-version>
<log4j-version>1.2.17</log4j-version>
<slf4j-version>1.7.5</slf4j-version>
<aspectj-version>1.7.4</aspectj-version>
<mybatis-version>3.2.2</mybatis-version>
<postgresql-version>9.1-901-1.jdbc4</postgresql-version>
</properties>
<dependencies>
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<!-- spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-version}</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j-version}</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis-version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql-version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
</project>
一:基本篇:
applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 启动注入功能 -->
<context:annotation-config />
<!-- 启动扫描component功能 -->
<context:component-scan base-package="com.tch.test.spring_mybatis" />
<!-- 启动注解实物配置功能 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"></property>
<property name="url" value="jdbc:postgresql://localhost:5432/postgres"></property>
<property name="username" value="postgres"></property>
<property name="password" value="postgres"></property>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--读取数据库配置文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--
如果mapper的xml文件名字和mapper接口的名字一致,并且在同一目录下(例如UserMapper.java和UserMapper.xml),可以不配置mapperLocations,
-->
<property name="mapperLocations" value="classpath:**/*Mapper.xml" />
<!-- 指定别名,在mapper的xml文件中可以使用别名(例如User/user来代表com.tch.test.spring_mybatis.entity.User),提高开发效率 -->
<property name="typeAliasesPackage" value="com.tch.test.spring_mybatis.entity" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定mapper接口包名,可以通过动态代理生成代理类,这样就可以在service层直接通过注入的方式进行dao操作了 -->
<property name="basePackage" value="com.tch.test.spring_mybatis.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
</beans>
log4j.properties:
log4j.rootLogger=debug,CONSOLE
###################
# Console Appender
###################
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=debug
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p (%c:%L) - %m%n
数据库创建脚本(注: 我使用的是postgresql,其他数据库可能不一样,根据情况做些修改):
CREATE TABLE _user
(
id bigint NOT NULL,
age bigint,
username character(15),
password character(20),
CONSTRAINT user_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE _user
OWNER TO postgres;
CREATE TABLE _order
(
orderNum bigint NOT NULL,
userId bigint NOT NULL,
CONSTRAINT order_pkey PRIMARY KEY (orderNum)
)
WITH (
OIDS=FALSE
);
ALTER TABLE _order
OWNER TO postgres;
CREATE TABLE orderDetail
(
id bigint NOT NULL,
orderNum bigint NOT NULL,
itemId bigint NOT NULL,
itemNum bigint NOT NULL,
CONSTRAINT order_detail_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE orderDetail
OWNER TO postgres;
CREATE TABLE item
(
id bigint NOT NULL,
itemName character(15),
price bigint,
CONSTRAINT item_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE item
OWNER TO postgres;
entity:
package com.tch.test.spring_mybatis.entity;
public class User {
private int id;
private String username;
private String password;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", age=" + age + "]";
}
}
UserMapper.java和UserMapper.xml在同一个目录下。
UserMapper.java:
package com.tch.test.spring_mybatis.mapper;
import com.tch.test.spring_mybatis.entity.User;
/**
*
* 方法名和mapper的xml中的select/insert/delete/update 的id一致,
* 方法的输入参数和parameterType一致,
* 方法的返回值和resultType一致
*
* @author dreamoftch
*/
public interface UserMapper {
User queryUserByID(int id);
void insertUser(User user);
void deleteUser(User user);
void updateUser(User user);
}
UserMapper.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">
<!-- 这里的namespace是mapper接口的全路径 -->
<mapper namespace="com.tch.test.spring_mybatis.mapper.UserMapper">
<!-- 下面的select/insert/delete/update 的id和mapper接口的方法名一致,parameterType和方法的输入参数一致,resultType和方法的返回值一致 -->
<select id="queryUserByID" parameterType="int" resultType="user">
select *
from _user
where id = #{id}
</select>
<insert id="insertUser" parameterType="com.tch.test.spring_mybatis.entity.User">
insert into _user(id, username, password, age)
values(#{id}, #{username}, #{password}, #{age})
</insert>
<delete id="deleteUser" parameterType="com.tch.test.spring_mybatis.entity.User">
delete from _user
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="username != null">
and username = #{username}
</if>
<if test="password != null">
and password = #{password}
</if>
<if test="age != null">
and age = #{age}
</if>
</where>
</delete>
<update id="updateUser" parameterType="com.tch.test.spring_mybatis.entity.User">
update _user
<set>
<if test="username != null">
username = #{username},
</if>
<if test="password != null">
password = #{password},
</if>
<if test="age != null">
age = #{age},
</if>
</set>
<!-- where id = #{id} -->
<where>
<if test="id != null">
id = #{id}
</if>
</where>
</update>
</mapper>
service接口:
package com.tch.test.spring_mybatis.service;
import com.tch.test.spring_mybatis.entity.User;
public interface IUserService {
User queryUserByID(int id) throws Exception;
void insertUser(User user) throws Exception;
void deleteUser(User user) throws Exception;
void updateUser(User user) throws Exception;
void raiseException() throws Exception;
/**
* test transaction
* @param user
* @throws Exception
*/
void testTransaction(User user) throws Exception;
/**
* test transaction2
* @param user
* @throws Exception
*/
void testTransaction2(User user) throws Exception;
}
service 实现类:
package com.tch.test.spring_mybatis.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.tch.test.spring_mybatis.entity.User;
import com.tch.test.spring_mybatis.mapper.UserMapper;
@Service("userService")
public class UserServiceImpl implements IUserService {
/**
* UserMapper接口并没有实现类,这里会注入一个该接口的代理类
*/
@Autowired
private UserMapper userMapper;
public User queryUserByID(int id) throws Exception {
return userMapper.queryUserByID(id);
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
public void insertUser(User user) throws Exception {
userMapper.insertUser(user);
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
public void deleteUser(User user) throws Exception {
userMapper.deleteUser(user);
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
public void updateUser(User user) throws Exception {
userMapper.updateUser(user);
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
public void testTransaction(User user) throws Exception {
// delete -> add -> add()
user.setId(user.getId() + 1); // new id
userMapper.insertUser(user); // insert
raiseException(); // raise exception
user.setUsername("update username");
userMapper.updateUser(user);
}
public void raiseException(){
boolean flag = true;
if(flag){
throw new IllegalStateException("Duang ...");
}
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })
public void testTransaction2(User user) throws Exception {
// delete -> add -> add()
user.setId(user.getId() + 1); // new id
insertUser(user);
raiseException(); // raise exception
user.setUsername("update username");
updateUser(user);
}
}
测试类:
package com.tch.test.spring_mybatis;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tch.test.spring_mybatis.entity.User;
import com.tch.test.spring_mybatis.service.IUserService;
/**
* Hello world!
*
*/
public class Test {
public static void main(String[] args) throws Exception {
int userId = 3;
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
IUserService service = (IUserService) context.getBean("userService");
// clear data
User user = service.queryUserByID(userId);
if(user != null){
service.deleteUser(user);
}
// insert
service.insertUser(createUser(userId));
// select
user = service.queryUserByID(userId);
System.out.println("result after insert: " + user);
// update
user.setUsername("张三");
service.updateUser(user);
// select
user = service.queryUserByID(userId);
System.out.println("result after update: " + user);
// delete
service.deleteUser(user);
// select
user = service.queryUserByID(userId);
System.out.println("result after delete: " + (user == null ? "null" : user));
service.testTransaction2(createUser(userId)); // test transaction
context.close();
}
private static User createUser(int id) {
User user = new User();
user.setId(id);
user.setAge(20);
user.setPassword("007");
user.setUsername("dreamoftch");
return user;
}
}
通过service层的testTransaction2方法 测试事务特性(出现异常的时候,是否会回滚)
OK, 自己通过测试这些方法就阔以了。。。
二:进阶篇:
下面是Mybatis 懒加载以及一对一,一对多的配置:
使用懒加载,需要在Mybatis的配置文件中开启懒加载,然后在collection/association的地方,如果需要使用懒加载,则需要指定select属性,也就是真正需要加载的时候,执行的sql statement的id,如果有参数,则通过column指定即可。
UserMapper.xml(同样的是跟UserMapper.java在同一目录下,替换前面的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">
<!-- 这里的namespace是mapper接口的全路径 -->
<mapper namespace="com.tch.test.spring_mybatis.mapper.UserMapper">
<!-- 下面的select/insert/delete/update 的id和mapper接口的方法名一致,parameterType和方法的输入参数一致,resultType和方法的返回值一致 -->
<resultMap type="com.tch.test.spring_mybatis.entity.User" id="userCumtom">
<id column="_user_id" property="id" />
<result column="username" property="username" />
<result column="password" property="password" />
<result column="age" property="age" />
<collection property="orders" ofType="com.tch.test.spring_mybatis.entity.Order">
<id column="orderNum" property="orderNum" />
<collection property="orderDetails" ofType="com.tch.test.spring_mybatis.entity.OrderDetail">
<id column="detail_id" property="id" />
<result column="orderNum" property="orderNum" />
<result column="item_id" property="itemId" />
<result column="itemNum" property="itemNum" />
<association property="item" javaType="com.tch.test.spring_mybatis.entity.Item">
<id column="item_id" property="id" />
<result column="itemName" property="itemName" />
<result column="price" property="price" />
</association>
</collection>
</collection>
</resultMap>
<resultMap type="com.tch.test.spring_mybatis.entity.User" id="lazyUserCumtom">
<id column="_user_id" property="id" />
<result column="username" property="username" />
<result column="password" property="password" />
<result column="age" property="age" />
<!-- 懒加载, 当需要用到该数据的时候,调用getOrdersByUser,并且用查询结果中的_user_id作为查询参数 -->
<collection property="orders" ofType="com.tch.test.spring_mybatis.entity.Order"
select="getOrdersByUser" column="_user_id">
</collection>
</resultMap>
<!-- 因为spring中配置了sqlSessionFactory的typeAliasesPackage,所以这里也可以用别名(首字母大小写都可以) -->
<resultMap type="order" id="lazyOrderCustom">
<id column="orderNum" property="orderNum" />
<!-- 懒加载, 当需要用到该数据的时候,调用getOrderDetailsByOrderNum,并且用查询结果中的orderNum作为查询参数 -->
<collection property="orderDetails" ofType="com.tch.test.spring_mybatis.entity.OrderDetail"
select="getOrderDetailsByOrderNum" column="orderNum">
</collection>
</resultMap>
<resultMap type="com.tch.test.spring_mybatis.entity.OrderDetail" id="lazyOrderDetailCumtom">
<id column="detail_id" property="id" />
<result column="orderNum" property="orderNum" />
<result column="itemId" property="itemId" />
<result column="itemNum" property="itemNum" />
<!-- 懒加载, 当需要用到item属性时, 调用同一namespace下的getItemById的select语句,并且将当前sql查询出来的itemId(如果该字段在多个表中有重名,则需要在sql中指定别名,在这里也使用该别名既可)字段作为输入参数 -->
<association property="item" javaType="com.tch.test.spring_mybatis.entity.Item" select="getItemById" column="itemId">
</association>
</resultMap>
<resultMap type="item" id="lazyItemCumtom">
<id column="item_id" property="id" />
<result column="itemName" property="itemName" />
<result column="price" property="price" />
</resultMap>
<select id="queryUserByID" parameterType="int" resultType="user">
select *
from _user
where id = #{id}
</select>
<select id="queryAllUserInfo" resultMap="userCumtom">
select u.id _user_id, detail.id detail_id, i.id
item_id, *
from _user u join _order o on u.id=o.userId
join orderDetail detail on
o.orderNum=detail.orderNum
join item i on detail.itemId=i.id
</select>
<select id="lazyLoadUserInfo" resultMap="lazyUserCumtom">
select u.id _user_id, u.*
from _user u
</select>
<select id="getOrdersByUser" parameterType="int" resultMap="lazyOrderCustom">
select * from _order
where userId
= #{userId}
</select>
<select id="getOrderDetailsByOrderNum" parameterType="int" resultMap="lazyOrderDetailCumtom">
select * from
orderDetail
where orderNum = #{orderNum}
</select>
<select id="getAllOrderDetails" resultMap="lazyOrderDetailCumtom">
select id detail_id, * from
orderDetail
</select>
<select id="getItemById" parameterType="int" resultMap="lazyItemCumtom" >
select * from item
where id = #{id}
</select>
<insert id="insertUser" parameterType="com.tch.test.spring_mybatis.entity.User">
insert into _user(id, username, password, age)
values(#{id}, #{username}, #{password}, #{age})
</insert>
<delete id="deleteUser" parameterType="com.tch.test.spring_mybatis.entity.User">
delete from _user
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="username != null">
and username = #{username}
</if>
<if test="password != null">
and password = #{password}
</if>
<if test="age != null">
and age = #{age}
</if>
</where>
</delete>
<update id="updateUser" parameterType="com.tch.test.spring_mybatis.entity.User">
update _user
<set>
<if test="username != null">
username = #{username},
</if>
<if test="password != null">
password = #{password},
</if>
<if test="age != null">
age = #{age},
</if>
</set>
<!-- where id = #{id} -->
<where>
<if test="id != null">
id = #{id}
</if>
</where>
</update>
</mapper>
sqlMapConfig.xml(可以直接放在classpath跟路径下):
<?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>
<settings>
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
</settings>
</configuration>
上面的spring的 applicationContext.xml做一点修改:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 启动注入功能 -->
<context:annotation-config />
<!-- 启动扫描component功能 -->
<context:component-scan base-package="com.tch.test.spring_mybatis" />
<!-- 启动注解实物配置功能 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"></property>
<property name="url" value="jdbc:postgresql://localhost:5432/test"></property>
<property name="username" value="postgres"></property>
<property name="password" value="postgres"></property>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--读取数据库配置文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 如果mapper的xml文件名字和mapper接口的名字一致,并且在同一目录下(例如UserMapper.java和UserMapper.xml),可以不配置mapperLocations, -->
<property name="mapperLocations" value="classpath:**/*Mapper.xml" />
<!-- 指定别名,在mapper的xml文件中可以使用别名(例如User/user来代表com.tch.test.spring_mybatis.entity.User),提高开发效率 -->
<property name="typeAliasesPackage" value="com.tch.test.spring_mybatis.entity" />
<!-- 指定mybatis配置文件位置,由于该配置文件中开启了懒加载的功能,所以需要这个配置 -->
<property name="configLocation" value="sqlMapConfig.xml"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定mapper接口包名,可以通过动态代理生成代理类,这样就可以在service层直接通过注入的方式进行dao操作了 -->
<property name="basePackage" value="com.tch.test.spring_mybatis.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!-- <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean> -->
</beans>
用到的entity:
package com.tch.test.spring_mybatis.entity;
import java.util.List;
public class User {
private int id;
private String username;
private String password;
private int age;
private List<Order> orders;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", age=" + age + ", orders=" + orders + "]";
}
}
package com.tch.test.spring_mybatis.entity;
import java.util.List;
public class Order {
private int orderNum;
private int userId;
private List<OrderDetail> orderDetails;
public int getOrderNum() {
return orderNum;
}
public void setOrderNum(int orderNum) {
this.orderNum = orderNum;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public List<OrderDetail> getOrderDetails() {
return orderDetails;
}
public void setOrderDetails(List<OrderDetail> orderDetails) {
this.orderDetails = orderDetails;
}
@Override
public String toString() {
return "Order [orderNum=" + orderNum + ", userId=" + userId + ", orderDetails=" + orderDetails + "]";
}
}
package com.tch.test.spring_mybatis.entity;
public class OrderDetail {
private int id;
private int orderNum;
private int itemId;
private int itemNum;
private Item item;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getOrderNum() {
return orderNum;
}
public void setOrderNum(int orderNum) {
this.orderNum = orderNum;
}
public int getItemId() {
return itemId;
}
public void setItemId(int itemId) {
this.itemId = itemId;
}
public int getItemNum() {
return itemNum;
}
public void setItemNum(int itemNum) {
this.itemNum = itemNum;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
@Override
public String toString() {
return "OrderDetail [id=" + id + ", orderNum=" + orderNum + ", itemId=" + itemId + ", itemNum=" + itemNum + ", item=" + item + "]";
}
}
package com.tch.test.spring_mybatis.entity;
public class Item {
private int id;
private String itemName;
private int price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Item [id=" + id + ", itemName=" + itemName + ", price=" + price + "]";
}
}
测试懒加载:
package com.tch.test.spring_mybatis;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tch.test.spring_mybatis.entity.OrderDetail;
import com.tch.test.spring_mybatis.entity.User;
import com.tch.test.spring_mybatis.mapper.UserMapper;
import com.tch.test.spring_mybatis.service.IUserService;
/**
* Hello world!
*
*/
public class Test {
public static void main(String[] args) throws Exception {
int userId = 3;
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserService service = (IUserService) context.getBean("userService");
/*// clear data
User user = service.queryUserByID(userId);
if(user != null){
service.deleteUser(user);
}
// insert
service.insertUser(createUser(userId));
// select
user = service.queryUserByID(userId);
System.out.println("result after insert: " + user);
// update
user.setUsername("张三");
service.updateUser(user);
// select
user = service.queryUserByID(userId);
System.out.println("result after update: " + user);
// delete
service.deleteUser(user);
// select
user = service.queryUserByID(userId);
System.out.println("result after delete: " + (user == null ? "null" : user));*/
// service.testTransaction2(createUser(userId));
// List<User> users = service.queryAllUserInfo();
// System.out.println(users);
// List<OrderDetail> orderDetails = service.getAllOrderDetails();
// for(OrderDetail orderDetail : orderDetails){
// System.out.println(orderDetail.getItemId());
// }
List<User> users = service.lazyLoadUserInfo();
for(User user : users){
System.out.println(user);
}
context.close();
}
private static User createUser(int id) {
User user = new User();
user.setId(id);
user.setAge(20);
user.setPassword("007");
user.setUsername("dreamoftch");
return user;
}
}
通过测试service层的lazyLoadUserInfo方法即可发现,在执行完lazyLoadUserInfo()方法只会,只是执行了select u.id _user_id, * from _user u 这一条SQL。
在循环体中,打印user的时候,由于调用了toString() 方法,此时发出了其他的order, orderDetail, Item 相关的 SQL。也就说明懒加载生效了。
MyBatis动态SQL示例:
<?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">
<!-- 这里的namespace是mapper接口的全路径 -->
<mapper namespace="com.tch.test.spring_mybatis.mapper.BlogMapper">
<!-- 下面的select/insert/delete/update 的id和mapper接口的方法名一致,parameterType和方法的输入参数一致,resultType和方法的返回值一致 -->
<!-- choose/when -->
<select id="findActiveBlogLike" resultType="com.tch.test.spring_mybatis.entity.Blog">
SELECT * FROM blog WHERE status = 'ACTIVE'
<!-- choose: 类似Java里面的switch, 都不为null的时候,哪个在前用哪个。 都为null的时候,忽略该标签 -->
<choose>
<when test="title != null">
AND title = #{title}
</when>
<when test="author != null">
AND author = #{author}
</when>
</choose>
</select>
<!-- where -->
<select id="findActiveBlogLike2" resultType="com.tch.test.spring_mybatis.entity.Blog">
SELECT * FROM blog
<!-- where: where 元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where
元素也知道如何将他们去除 -->
<where>
<if test="status != null">
AND status = #{status}
</if>
<if test="title != null">
AND title = #{title}
</if>
<if test="author != null">
AND author = #{author}
</if>
</where>
</select>
<!-- trim -->
<select id="findActiveBlogLike3" resultType="com.tch.test.spring_mybatis.entity.Blog">
SELECT * FROM blog
<!-- trim: 使用trim来实现和上面的where完全一样的功能 -->
<trim prefix="where" prefixOverrides="AND |OR ">
<if test="status != null">
AND status = #{status}
</if>
<if test="title != null">
AND title = #{title}
</if>
<if test="author != null">
AND author = #{author}
</if>
</trim>
</select>
<!-- set -->
<update id="updateBlog" parameterType="com.tch.test.spring_mybatis.entity.Blog">
update blog
<!-- set: set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号 -->
<set>
<if test="status != null">
status = #{status},
</if>
<if test="title != null">
title = #{title},
</if>
</set>
<where>
<if test="author != null">
author = #{author}
</if>
</where>
</update>
<!-- trim -->
<update id="updateBlog2" parameterType="com.tch.test.spring_mybatis.entity.Blog">
update blog
<!-- trim: 实现上面set一样的功能 -->
<trim prefix="SET" suffixOverrides=",">
<if test="status != null">
status = #{status},
</if>
<if test="title != null">
title = #{title},
</if>
</trim>
<where>
<if test="author != null">
author = #{author}
</if>
</where>
</update>
<!-- foreach -->
<select id="findActiveBlogLike4" resultType="com.tch.test.spring_mybatis.entity.Blog">
SELECT * FROM blog WHERE author in
<!-- foreach: foreach 元素的功能是非常强大的,它允许你指定一个集合,声明可以用在元素体内的集合项和索引变量。它也允许你指定开闭匹配的字符串以及在迭代中间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符 -->
<foreach item="author" index="index" collection="authors" open="(" separator="," close=")">
#{author}
</foreach>
</select>
</mapper>
package com.tch.test.spring_mybatis.entity;
public class Blog {
private String state;
private String title;
private String author;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Blog [state=" + state + ", title=" + title + ", author="
+ author + "]";
}
}
package com.tch.test.spring_mybatis.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.tch.test.spring_mybatis.entity.Blog;
public interface BlogMapper {
void updateBlog(@Param("status") String status, @Param("author") String author, @Param("title") String title);
void updateBlog2(@Param("status") String status, @Param("author") String author, @Param("title") String title);
List<Blog> findActiveBlogLike(@Param("status") String status, @Param("author") String author, @Param("title") String title);
List<Blog> findActiveBlogLike2(@Param("status") String status, @Param("author") String author, @Param("title") String title);
List<Blog> findActiveBlogLike3(@Param("status") String status, @Param("author") String author, @Param("title") String title);
List<Blog> findActiveBlogLike4(@Param("authors") List<String> authors);
}
测试:
package com.tch.test.spring_mybatis;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tch.test.spring_mybatis.entity.Blog;
import com.tch.test.spring_mybatis.entity.User;
import com.tch.test.spring_mybatis.mapper.BlogMapper;
/**
* Hello world!
*
*/
public class Test {
public static void main(String[] args) throws Exception {
int userId = 3;
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BlogMapper blogMapper = context.getBean(BlogMapper.class);
List<String> authors = new ArrayList<String>();
authors.add("chaohui-1");
authors.add("chaohui-2");
List<Blog> blogs = blogMapper.findActiveBlogLike4(authors);
System.out.println(blogs);
// blogMapper.updateBlog2("ACTIVE", "chaohui-1", "title-1");
/*// clear data
User user = service.queryUserByID(userId);
if(user != null){
service.deleteUser(user);
}
// insert
service.insertUser(createUser(userId));
// select
user = service.queryUserByID(userId);
System.out.println("result after insert: " + user);
// update
user.setUsername("张三");
service.updateUser(user);
// select
user = service.queryUserByID(userId);
System.out.println("result after update: " + user);
// delete
service.deleteUser(user);
// select
user = service.queryUserByID(userId);
System.out.println("result after delete: " + (user == null ? "null" : user));*/
// service.testTransaction2(createUser(userId));
// List<User> users = service.queryAllUserInfo();
// System.out.println(users);
// List<OrderDetail> orderDetails = service.getAllOrderDetails();
// for(OrderDetail orderDetail : orderDetails){
// System.out.println(orderDetail.getItemId());
// }
// List<User> users = service.lazyLoadUserInfo();
// for(User user : users){
// System.out.println(user);
// }
context.close();
}
private static User createUser(int id) {
User user = new User();
user.setId(id);
user.setAge(20);
user.setPassword("007");
user.setUsername("dreamoftch");
return user;
}
}
|
|