关于 JPA 连表查询和 redis 序列化遇到的小问题
一、JPA
1. 连表查询时数据长度正常,内容都是重复的,MySQL 数据库运行查询语句结果正常
先看写法:
package cn.bridgeli.demo.repository; import cn.bridgeli.demo.entity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import java.util.List; /** * @author BridgeLi */ public interface E1Repository extends JpaRepository<E1, Integer> { @Query(value = "SELECT t1.id, t1.name, t2.score FROM t1 LEFT JOIN t2 ON t1.id = t2.t1_id LIMIT ?1, ?2", nativeQuery = true) List<E1> queryE1s(Integer pageNum, Integer pageSize); } package cn.bridgeli.demo.entity; import lombok.Data; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Transient; /** * @author BridgeLi */ @Data @Entity public class E1 { @Id private Integer id; private String name; @Transient private String course; private Integer score; }
整体大概就是有两张表 t1 和 t2,一对多的关系,t1 的主键是 t2 的外键,执行的截图我就不做了,问题呢,大概就是上面描述的那样,有一个连表查询的需求,JPA 做的,返回给前端的数据,返回长度是对的,但是内容都是重复的,当时第一次看到这个问题的时候,怀疑是 SQL 的问题,然后就把
原因:JPA 映射 entity 时,是根据 id 来居分不同实体的,id 相同,则认为是同一条记录,会重复记录,而不会分别记录其它字段不同的值
解决方案:知道了原因就很容易解决了,只需要一对多,不要用一的那张表做主键用多的那张表做主键就好了。
2. 查询的时候列不存在
这个不是我遇到过,之前听某个同事说,用 JPA 查询的时候,报某个列不存在,而他没有写要查询这个列,当时忙其他的事没有在意,后面也没有关注和测试,个人猜测可以用我上面写的 @Transient 标签来解决。@Transient 表示该属性并非一个到数据库表的字段的映射,忽略该属性。如果一个属性并非数据库表的字段映射,就务必将其标示为 @Transient,否则默认其注解为 @Basic。
2. Redis 时不时的会报一个错:java.lang.String cannot be cast to java.lang.Long,代码如下:
public String getSerialNumber() { ValueOperations<String, Long> operations = redisTemplate.opsForValue(); String today = DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMdd")); Long serial = Long.valueOf(new StringBuffer(today).append("001").toString()); Boolean result = operations.setIfAbsent(today, serial); if (!result) { serial = operations.increment(today, 1); redisTemplate.expire(today, 1, TimeUnit.DAYS); } return serial.toString(); }
然后定位了一下,就是 Redis 序列化的时候报的错,看一下序列化的方式吧:
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="valueSerializer" ref="jackson2JsonRedisSerializer"/> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer" ref="jackson2JsonRedisSerializer"/> </bean> <bean id="jackson2JsonRedisSerializer" class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"> </bean>
没发现有什么问题啊,当时应急就出现了重启一下解决,为什么想到重启一下解决呢,因为上线的时候测试了一下没有问题的,所以想着重启一下是不是就好了,试了一下还真解决了,所以就这么干了两次,差点怀疑是不是 spring-data-redis 有 bug,其实不可能的,不是说 spring-data-redis 不可能有 bug,而是这么小的概率,这么严重的 bug,怎么可能别人都遇不到就我们遇到了,而且网上还没人说?后面闲的时候想这个问题不应该啊,重启解决也不是事,还是得从根本上解决,所以就看了一下代码,搜了一下序列化的地方,这么一查还真遇到了,在另一个地方,有个同事不知道咋回事写了个这玩意:
redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer());
也就是在那个地方修改了序列化方式,当这个地方被执行了一次之后,序列化方式就被修改了,所以启动的时候配置的序列化方式就不行了,然后再次执行的就报错了,找到原因,然后就好解决了,问同事为什么这个地方修改序列化方式,有什么原因吗?不改行不行,同事:在网上抄的这段代码,不知道为什么,不改应该也可以,遂删除完事,经测试无误,后面再未出现。
总结:其实今天写的三个问题,都是非常小的问题,原因也都很简单,相关的程序员对自己使用的框架不熟,然后瞎写出错,这个就要求我们第一步模仿别人写没有问题,毕竟要快速完成功能,但是写完之后一定要测试,写的对不对,对其他地方有没有影响,完成功能之后,能不能看一下文档或者资料,看看自己写的这段代码啥意思,为什么这么写,这么写会不会有什么没发现的问题,这样才能提高自己,而不是写完完事,哪管后面洪水滔天。
作 者: BridgeLi,https://www.bridgeli.cn
原文链接:http://www.bridgeli.cn/archives/668
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。
近期评论