整體思路
之前已經有人做過mybatis+redis在spring環境的集成(http://blog.csdn.net/xiadi934/article/details/50786293)。 這裏我們試試在spring boot中的集成,其中的一些注意點是不同的。特別是spring boot 的對mybatis的集成時候可以非常簡單,但是在加入二級緩存時候,我們要考慮mybatis的配置。
pom 中加入依賴
<boot.version>1.3.1.RELEASE</boot.version>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>${boot.version}</version>
</dependency>
applicationContext-cache.xml中引入redis配置
<!-- redis數據源 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${spring.redis.maxIdle}" />
<property name="maxTotal" value="${spring.redis.maxActive}" />
<property name="maxWaitMillis" value="${spring.redis.maxWait}" />
<property name="testOnBorrow" value="${spring.redis.testOnBorrow}" />
</bean>
<!-- Spring-redis連接池管理工廠 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${spring.redis.host}" p:port="${spring.redis.port}" p:password="${spring.redis.password}" p:pool-config-ref="poolConfig"/>
<!-- 使用中間類解決RedisCache.jedisConnectionFactory的靜態注入,從而使MyBatis實現第三方緩存 -->
<bean id="redisCacheTransfer" class="com.wedo.stream.cache.RedisCacheTransfer">
<property name="jedisConnectionFactory" ref="jedisConnectionFactory"/>
</bean>
實現Cache接口
這個和原來的完全一致。
RedisCache
public class RedisCache implements Cache {
private static Logger LOGGER = LoggerFactory.getLogger(RedisCache.class);
private static JedisConnectionFactory jedisConnectionFactory;
private final String id;
/**
* The {@code ReadWriteLock}.
*/
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
LOGGER.debug("MybatisRedisCache:id=" + id);
this.id = id;
}
@Override
public void clear() {
JedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
connection.flushDb();
connection.flushAll();
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
}
@Override
public String getId() {
return this.id;
}
@Override
public Object getObject(Object key) {
Object result = null;
JedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
result = serializer.deserialize(connection.get(serializer.serialize(key)));
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
@Override
public int getSize() {
int result = 0;
JedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
result = Integer.valueOf(connection.dbSize().toString());
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
@Override
public void putObject(Object key, Object value) {
JedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
}
@Override
public Object removeObject(Object key) {
JedisConnection connection = null;
Object result = null;
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
result = connection.expire(serializer.serialize(key), 0);
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.jedisConnectionFactory = jedisConnectionFactory;
}
}
RedisCacheTransfer
public class RedisCacheTransfer
{
@Autowired
public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.setJedisConnectionFactory(jedisConnectionFactory);
}
}
配置文件application.yml 中添加
#Redis settings
spring:
redis:
host: 127.0.0.1
password: aaa
port: 6379
mybatis:
mapperLocations: classpath*:com/wedo/stream/dao/xml/*.xml
typeAliasesPackage: com.wedo.stream.dao.entity
configLocation: classpath:mybatis-config.xml
Mybatis全局配置mybatis-config.xml
注意這個原本是不需要的,並且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>
<settings>
<!-- 開啓駝峯匹配 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
<!-- 這個配置使全局的映射器啓用或禁用緩存。系統默認值是true,設置只是爲了展示出 來 -->
<setting name="cacheEnabled" value="true" />
<!-- 全局啓用或禁用延遲加載。當禁用時,所有關聯對象都會即時加載。 系統默認值是true,設置只是爲了展示出來 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 允許或不允許多種結果集從一個單獨的語句中返回(需要適合的驅動)。 系統默認值是true,設置只是爲了展示出來 -->
<setting name="multipleResultSetsEnabled" value="true" />
<!--使用列標籤代替列名。不同的驅動在這方便表現不同。參考驅動文檔或充分測試兩種方 法來決定所使用的驅動。 系統默認值是true,設置只是爲了展示出來 -->
<setting name="useColumnLabel" value="true" />
<!--允許 JDBC 支持生成的鍵。需要適合的驅動。如果設置爲 true 則這個設置強制生成的鍵被使用,儘管一些驅動拒絕兼容但仍然有效(比如
Derby)。 系統默認值是false,設置只是爲了展示出來 -->
<setting name="useGeneratedKeys" value="false" />
<!--配置默認的執行器。SIMPLE 執行器沒有什麼特別之處。REUSE 執行器重用預處理語句。BATCH 執行器重用語句和批量更新 系統默認值是SIMPLE,設置只是爲了展示出來 -->
<setting name="defaultExecutorType" value="SIMPLE" />
<!--設置超時時間,它決定驅動等待一個數據庫響應的時間。 系統默認值是null,設置只是爲了展示出來 -->
<setting name="defaultStatementTimeout" value="25000" />
</settings>
</configuration>
mapper中加入MyBatis二級緩存
<mapper namespace="com.wedo.stream.dao.mapper.SorterMapper" >
<cache type="com.wedo.stream.cache.RedisCache" />
.....
</mapper>
實體類實現 Serializable
public class Sorter implements Serializable
測試
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/spring-dao.xml","/applicationContext-cache.xml"})
@ActiveProfiles(value="dev")
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class })
public class CacheTest {
private static Logger LOGGER = LoggerFactory.getLogger(CacheTest.class);
@Autowired
private SorterMapper mapper;
@Test
public void test(){
Date start = new Date();
for(int i=0;i<100;i++){
mapper.getall();
}
Date end = new Date();
long duration = end.getTime()-start.getTime();
LOGGER.info(duration);
}
}
測試結果,如果打開二級緩存,用時363毫秒,如果關閉二級緩存用時6秒+,平均一次查詢50毫秒。