Spring data jpa @MapKeyColumn的查询处理

本文介绍了在SpringData JPA中实现“纵表”设计的方法,即在一个主表和多个从表间建立一对多的关系,并通过Map类型存储从表的键值对。文章详细探讨了如何使用@ElementCollection等注解实现这一设计,并解决了在查询过程中遇到的问题。
部署运行你感兴趣的模型镜像
最近在使用Spring Data JPA, 查询起来还是比较方便的。简单看了下@Query支持的,其实叫JPQL,是JPA规范中提出的一种面向对象的查询方式,其实JPQL只是HQL的子集(毕竟JPA源于Hibernate),不过HQL原本我也不熟,所以还是需要一段时间来看看JPA2的规范,貌似现在对聚合查询,子查询等功能都支持的不错了。不过网上的资料还是不多,感觉现在国内互联网还是以Mybatis为主要ORM框架,毕竟SQL是可以完全自定义的。其实Spring data JPA也可以通过native=true来完成。

言归正传,最近用到了"纵表"的设计,主表跟从表是一对多关系,从表是个简单的key:value对,另外还有个外键用来关联主表主键。

主表:主表ID,名称,XXX
从表:从表ID,主表ID,Key,Value

持久化对象的类上只需要在主表的类中加入一个Map的属性,就能把从表的键值对加载过来,假设主表是一个Group表,从表是一个Group_params表:

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "GROUP_PARAMS", joinColumns = @JoinColumn(name = "GROUP_ID"))
@MapKeyColumn(name = "PARAM_KEY")
@Column(name = "PARAM_VALUE")
private Map<String, String> groupParams = new HashMap<String, String>();



在做完了这些之后,在增删改的时候都能以groupParams这个属性来拿到从表中的相关数据。

但是查询的时候遇到了一些问题,例如:根据param的Key和value查询group。

第一是要解决怎么写的问题,JPQL中使用了"Path Expressions"的方式来获取属性,也对Map这种数据结构提供了方法: KEY, VALUE, ENTRY, 也对应了Map当中的属性。
用法(以下写法有问题):

@Query(value = "select g from MyGroup g join g.groupParams p where KEY(p) = :paramKey and VALUE(p) = :paramValue ")

用了上述的注解后生成的native SQL(重点在查询条件):
where groupparam1_.param_key=? and (select groupparam1_.param_value from group_params groupparam1_ where mygroup0_.group_id=groupparam1_.group_id)=?;

可以看到查询是有问题的,Value方法直接导致生成了子查询。解决方法是把第二个查询条件的 VALUE(p) = :paramValue 直接修改为p=:paramValue.

具体的原因我只能通过查询获取一点信息,没有从源码级别看,hibernate东西还是挺多的,相关链接见:
https://stackoverflow.com/questions/29852701/is-it-possible-to-query-jpa-entities-by-elementcollections-where-the-elementcoll

https://stackoverflow.com/questions/21263725/jpas-mapkey-value-query-by-jpql-failed

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

### 整合Spring Boot与Spring Data JPA并使用`@Lock`注解 在Spring Boot项目中整合Spring Data JPA,并利用`@Lock`注解来处理并发访问问题是一个常见的需求。通过这种方式,能够有效地管理数据的一致性和完整性。 #### 配置依赖项 为了使Spring Data JPA正常工作,在项目的`pom.xml`文件中需引入必要的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 如果使用MySQL --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> ``` 上述配置确保了JPA以及特定数据库驱动程序被正确加载到应用环境中[^1]。 #### 创建实体类 定义一个简单的Java实体类映射至数据库表。这里以`User`为例展示基本结构: ```java import javax.persistence.Entity; import javax.persistence.Id; @Entity public class User { @Id private Long id; private String name; // getters and setters omitted for brevity } ``` 此部分展示了如何创建持久化对象模型以便于后续操作[^2]。 #### 使用`@Lock`实现乐观锁机制 当多个事务试图同时修改同一记录时,可以通过设置锁定模式来防止潜在的数据竞争条件。下面的例子说明了怎样运用`@Lock(LockModeType.OPTIMISTIC)`来进行读取期间加锁控制: ```java import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Lock; import jakarta.persistence.LockModeType; public interface UserRepository extends JpaRepository<User, Long> { @Lock(LockModeType.OPTIMISTIC) Optional<User> findById(Long userId); } ``` 这段代码片段表明了如何扩展标准仓库接口并通过指定方法上的`@Lock`参数来自定义查询行为。 #### 数据库平台配置注意事项 值得注意的是,虽然某些情况下可以省略显式的数据库连接属性声明,但在实际开发过程中建议始终明确定义这些细节。这有助于提高系统的健壮性并减少因环境差异带来的不确定性因素影响[^3]。 对于具体的数据库类型(如PostgreSQL),应在application.properties或application.yml文件内提供相应的URL、用户名及密码等信息: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=password ``` 以上内容解释了为何即使框架支持自动探测也不应忽视手动设定的重要性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值