在Spring Data JDBC中使用带@Id注释的复合实体会有什么影响?

问题描述

在我的Spring Data JDBC项目中,我有一个如下所示的复合实体类,可以将其映射到表item

字段idcodeitemName来自表item,而字段groupName属于另一个item_group

通过在存储库中使用自定义查询,我成功加载了此实体对象,如下所示:

"SELECT a.id,a.code,a.name AS item_name,b.name as group_name from item a LEFT JOIN item_group b ON a.group_id = b.id where a.id=:id")

拥有这样一个带有@Id注释的复合类是否有影响?

public class Item 
{
    @Id
    private long id;
    private String code;
    private String itemName;
    private String groupName;
    
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getItemName() {
        return itemName;
    }
    public void setItemName(String itemName) {
        this.itemName = itemName;
    }
    public String getGroupName() {
        return groupName;
    }
    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

解决方法

乍一看,这看起来确实没问题。

您将无法加载,更不用说使用标准CRUD方法保存它了。

它看起来也不对,因为您似乎正在合并两个聚合:ItemGroup,它们实际上应该是单独的聚合,它们之间没有Java引用。参见Spring Data JDBC,References,and Aggregates

但是,如果您认为它是针对特定上下文的视图,则确实有意义。 如果只需要它来从数据库中读取,则这是一种非常有效的方法。它简单高效,因为它一次选择即可加载所有必需的数据。

假设这是您所处的情况,我将建议以下内容:

  1. 在数据库中为联接创建一个视图。否则,该联接将在每个查询中一遍又一遍地重复。
  2. 如果您有这样的视图,则实际上可以删除@Query批注,而仅使用标准的find...方法。
  3. 不要让您的存储库扩展CrudRepository,而只能扩展Repository并仅手动添加您实际需要的方法。这样可以避免混淆,并且很明显,该存储库及其实体只能用于读取。
  4. 如果您使用标准的find...方法,则必须具有正确注释的id属性。如果您不使用find...方法,则@Id注释是多余的。