0%

SpringBoot + mybatis + redis 整合遇到的坑

目录

  1. 开发者工具
  2. Consider defining a bean of type ‘xx.xx.xx.dao.xxMapper’ in your configuration.
  3. mybatis代码自动生成工具Exception getting JDBC Driver
  4. 数据存入redis 序列化的问题
  5. maven执行install时自动运行mybatis-generator插件

开发工具及环境

工具:IDEA

环境:SpringBoot、mybatis、JDK11、MySQL80、redis

坑一:Consider defining a bean of type ‘xx.xx.xx.dao.xxMapper’ in your configuration.

网上的解决方法大概有三种:

  1. 在每个Mapper类上添加注解@Mapper,如
1
2
3
4
5
6
7
8
9
10
11
12
@Mapper
public interface TestMapper {
int deleteByPrimaryKey(String testId);

int insert(Test record);

Test selectByPrimaryKey(String testId);

List<Test> selectAll();

int updateByPrimaryKey(Test record);
}
  1. 在SpringBoot启动类上添加注解@MapperScan(“xx.xx.xx.dao”),引号内容是Mapper类所在的包名,如
1
2
3
4
5
6
7
8
@SpringBootApplication
@MapperScan("com.gwg.bwtgame.dao")
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}

}
  1. 在SpringBoot启动类上添加注解@ComponentScan( “xx.xx.xx.dao”)。注意此注解可以同时扫描多个包,格式为:@ComponentScan( {“xx.xx.xx.dao”, “xx.xx.xx.entity”})
1
2
3
4
5
6
7
@SpringBootApplication
@ComponentScan("xx.xx.xx.dao")
public class TestApplication {s
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}

原因:bean注入失败,启动类和相应的包名没在同一级目录下,注解@SpringBootApplication只能扫描同级目录下以及子目录下的包。以下是正确的:

目录

如果经过上述过程还没解决,请看一下你的maven是不是在使用IDEA默认的,如果是请自己下一个,改为自己的,IDEA默认的maven可能会有版本问题——这是在一个论坛上看到的,因为已经过去了一段时间,所以找不到那个网页了。我就是因为这个原因整整卡了两天。

坑二:mybatis代码自动生成工具Exception getting JDBC Driver

这个是在使用mybatis-generator工具时遇到的,一直报错找不到JDBC驱动类,之后网上搜需要在pom文件里将generator插件改为如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<!--以下dependencies标签中的内容是添加的内容-->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
<configuration>
<overwrite>true</overwrite>
<verbose>true</verbose>
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
</configuration>
</plugin>
</plugins>
</build>

坑三:数据存入redis 序列化的问题

慕课视频开始学的redis缓存,然后又结合网上的例子开始写了。

一开始开始采用重写RedisTemplete和自编RedisUtil工具类的方法去写,然后这种方法很难(可能是我不知道)与mybatis结合,必须自己实现dao接口。

然后采用注解@Cacheable方式,这就很方便了,可以很容易结合mybatis。然后问题来了在@Cacheable( value=”test”,key=”‘getById’+#id”)是一直报错,一直说参数无法序列化:

1
DefaultSerializer requires a Serializable payload but received an object of type

参数id类型为int甚至改为了String,都不行,然后网上找解决方法在这里直接将博主的RedisConfig配置类复制后就可以了,以下是我的和博主的对比:

我的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package xx.xx.xx.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;


@Configuration
@EnableCaching //开启注解
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
RedisCacheConfiguration redisCacheConfiguration=RedisCacheConfiguration.defaultCacheConfig();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
redisCacheConfiguration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
redisCacheConfiguration.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
@Bean
@ConditionalOnMissingBean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
RedisTemplate<String ,Object> redisTemplate=new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setEnableTransactionSupport(true);
ObjectMapper objectMapper=new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* hash类型配置
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* 对redis字符串类型数据操作
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
/**
* 对链表类型的数据操作
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* 对无序集合类型的数据操作
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* 对有序集合类型的数据操作
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}

博主的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package xx.xx.xx.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(serializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
/**
* 二者选其一即可
*/
// @Bean
// public RedisCacheConfiguration redisCacheConfiguration() {
// Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
// ObjectMapper objectMapper = new ObjectMapper();
// objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// serializer.setObjectMapper(objectMapper);
// return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));
// }
}

现在还是有点迷糊,不知道哪里配置不对了,key和value也都设置了序列化机制,但不知为什么不生效。不过现在是可以了,以后再研究。

坑四:maven执行install时自动运行mybatis-generator插件

后台代码写了个测试demo,可运行,想想着打包在服务器上运行试试,然后maven的clean、install,打包成功,有warning,没管,然后本地运行,报错找不到mapper类的bean,然后去看mapper的配置文件,发现里边有两个一模一样的bean,熟悉的配方,确认是代码生成工具的锅,删掉多余的,运行成功,然后又clean、install、运行有报错、找不到bean、看来是generator工具会自动在install时运行,找资料,相关博文貌似不是很多,但还是解决了一下摘自使用mybatis-generator插件后的maven打包问题:

原因:是因为mybatis-generator插件默认绑定了package的生命周期

解决:在pom中手动设置一下mybatis-generator插件绑定的生命周期即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<!--解决mybatis代码自动生成工具随maven打包运行的问题-->
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<phase>deploy</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
<configuration>
<overwrite>true</overwrite>
<verbose>true</verbose>
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
</configuration>
</plugin>