hibernate - JPA 实体和表 ID 作为字符串
问题描述
我正在使用 MySQL,并且有一个表包含与其他表中的 id 相关的数据 json 数据,而不是中间表
目前有 3 个表:Customers、Assets 和 Table XXX,其中有 3 列:id、name 和 myData。这是一个示例行:
1, "Some name",
[
{"customerId": 1, "assets": {"active": [10, 12, 13], "inactive": [15, 16]}}",
{"customerId": 2, "assets": {"active": [40, 42], "inactive": [19]}}"
]
顺便说一句,我不能改变设计:(
以下是实体:
@Table(name = "xxx")
class XXX {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
private String name;
String myData;
}
@Table(name = "assets")
class Asset {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
private String name;
}
@Table(name = "customers")
class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
private String name;
}
但是,我希望实体 XXX 正确映射实体并拥有客户和资产数据,类似于:
@Table(name = "xxx")
class XXX {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
private String name;
//maybe some awesome annotation here?
List<CustomerAssetsItem> customerAssetsItemsActive;
//maybe some awesome annotation here?
List<CustomerAssetsItem> customerAssetsItemsInactive;
}
CustomerAssetsItem 看起来像:
class CustomerAssetsItem {
Customer customer;
List<Asset> assets;
}
JPA甚至可以吗?或者我应该只创建一个解析 json 字符串的新服务,运行我需要的所有查询来构建层次结构?谢谢!
解决方案
有可能,看这个例子:JSON Attribute converter
您所要做的就是提供一个AttributeConverter
将 JSON 字符串映射到您的列表或其他任何内容的方法。
在您的实体上,您必须通过注释转换器类@Converter
@Table(name = "xxx")
class XXX {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
private String name;
@Converter(converter = CustomerAssetsConverter.class)
List<CustomerAssetsItem> customerAssetsItems;
}
而且你必须提供你自己的转换器,这只是一个草稿。您需要添加一个 JSON 对象映射器。此外,如果您想解析 JSON 中的客户 ID 引用,您需要自己的反序列化器,用于customerId: 1
映射执行查询以获取该客户。请参阅此示例:杰克逊自定义反序列化器
您可能不想解析引用,因为它们可能会导致大量查询,而且您很可能需要调整很多设置以不以无限循环结束。
我建议启用二级缓存并适当地使用@Transactional。
@Converter
public class CustomerAssetsConverter implements AttributeConverter<CustomerAssetsItem, String> {
//Add object mapper and repository
@Override
public String convertToDatabaseColumn(CustomerAssetsItem item) {
String itemJSON = null;
try {
itemJSON = objectMapper.writeValueAsString(item);
} catch (final JsonProcessingException e) {
}
return itemJSON;
}
@Override
public Map<String, Object> convertToEntityAttribute(String itemJSON) {
CustomerAssetsItem item = null;
try {
item = objectMapper.readValue(itemJSON, CustomerAssetsItem.class);
} catch (final IOException e) {
}
return item;
}
}
推荐阅读
- android - Android 圆角 - XML 与 Java 版本
- node.js - 如何正确地将我的 index.js 拆分为 server.js 和 app.js?
- javascript - 使用条件映射函数转换数组
- python - 如何找到两个巨大的numpy数组的交集
- file - 复制大文件在颤动中不起作用
- delphi - Delphi 7 在运行时创建 tChart Bar Pyramids / Cylinders
- javascript - 努力使用 Ramda.js 重构它,这是我得到的
- javascript - 如何使用 insertCell() 添加数据列?
- selenium - 对节点执行测试会产生错误
- python - Django 管理表单验证