JPA实体和表ID作为字符串

时间:2019-06-21 19:19:40

标签: hibernate spring-boot jpa spring-data-jpa

我正在使用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字符串的新服务,运行我为构建层次结构而执行的所有查询? 谢谢!

1 个答案:

答案 0 :(得分:0)

可能会看到以下示例: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映射执行查询以获取该客户。请参见以下示例:Jackson Custom Deserializer

可能不想解析引用,因为它们可能导致大量查询,而且您很可能需要调整很多设置以免陷入无限循环。

我建议启用二级缓存并适当使用@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;
    }
}