Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate 查询存储在单独集合中的@Embeddeble对象_Hibernate_Jpa_Spring Data Jpa_Spring Data - Fatal编程技术网

Hibernate 查询存储在单独集合中的@Embeddeble对象

Hibernate 查询存储在单独集合中的@Embeddeble对象,hibernate,jpa,spring-data-jpa,spring-data,Hibernate,Jpa,Spring Data Jpa,Spring Data,我有一个简单的关系,其中一个实体有许多特定于它的地址,定义为: @Entity public class Corporation { @Id private Long id; @ElementCollection @CollectionTable(name = "addresses_table", joinColumns = @JoinColumn(name = "corporation_id")) private List<Address>

我有一个简单的关系,其中一个实体有许多特定于它的地址,定义为:

@Entity
public class Corporation {

    @Id
    private Long id;

    @ElementCollection
    @CollectionTable(name = "addresses_table", joinColumns = @JoinColumn(name = "corporation_id"))
    private List<Address> addresses = new ArrayList<>();
}
@实体
公营公司{
@身份证
私人长id;
@元素集合
@CollectionTable(name=“addresses\u table”,joinColumns=@JoinColumn(name=“corporation\u id”))
私有列表地址=新的ArrayList();
}
地址
类用
@embeddeble
注释。这非常有效,因为公司的每次更新都会删除其所有地址,然后插入新地址。这正是我想要的行为。我尝试过的其他选项(
OneToMany
ManyToMany
)导致性能较差,因为我需要跳转,仍然无法获得简单的全部删除+全部插入行为

然而,有一个简单的要求,我需要能够查询一些标准的地址。基本上,这归结为一个简单的
findAll(Pageable-Pageable,Specification spec)
方法。这对于当前和未来的用例来说已经足够了

现在的问题是,可嵌入对象不是实体,因此我无法为它们创建Spring数据存储库。我能想到的唯一选择是:

  • 使用本机实体管理器实现自定义repo,但我不确定如何在代码方面以最佳方式实现,以及它是否能够支持通用
    规范
    。如果没有,我仍然可以接受,因为搜索地址的字段不会改变

  • 执行一些连接查询,如
    从Corporation c join c.addresses中选择sth,然后根据地址属性限制结果。在这里,我再次不确定这是否有效,是否与直接对addresses表进行简单排队一样有效


  • 如有任何建议,将不胜感激,无论是在所描述的选项上还是在某些其他选项上。

    单个表都可以映射到不同的类。因此,为什么不创建另一个
    地址
    类,它是一个常用的
    @实体
    类,以便您可以为它创建一个存储库,并使用您想要使用的
    规范

    @embeddeble
    地址
    可被视为
    公司
    的一个内部类,用于提供“全部删除+全部插入”行为。如果您希望域客户端只处理一个
    地址
    类,您可以简单地在
    @可嵌入
    地址和
    @实体
    地址之间进行转换

    代码方面,它看起来像:

    @Entity
    public class Corporation {
    
        @Id
        private Long id;
    
        @ElementCollection
        @CollectionTable(name = "addresses_table", joinColumns = @JoinColumn(name = "corporation_id"))
        private List<CorporationAddress> addresses = new ArrayList<>();
    
    
        public void addAddress(Address address){
           addresses.add(new CorporationAddress(address));
        }
    
        public List<Address> getAddresses(){
           return addresses.stream()
                .map(CorporationAddress::toAddress).collect(toList());
        }
    
    }
    
    
    //Or you can put it as the internal static nested class inside Corporation if you like
    @Embeddable
    public class CorporationAddress {
    
        //Create from Address
        public CorporationAddress(Address){
        }
    
        //Convert to Address
        public Address toAddress(){
    
        }
    
    }
    
    @Entity
    public class Address {
    
    
    } 
    
    @实体
    公营公司{
    @身份证
    私人长id;
    @元素集合
    @CollectionTable(name=“addresses\u table”,joinColumns=@JoinColumn(name=“corporation\u id”))
    私有列表地址=新的ArrayList();
    公共无效地址(地址){
    地址。添加(新公司地址(地址));
    }
    公共列表getAddresses(){
    返回地址。stream()
    .map(CorporationAddress::toAddress).collect(toList());
    }
    }
    //如果愿意,也可以将其作为公司内部的内部静态嵌套类
    @可嵌入
    公共类公司地址{
    //从地址创建
    公共公司地址(地址){
    }
    //转换为地址
    公共广播地址{
    }
    }
    @实体
    公共课堂演讲{
    } 
    
    如果在您的项目中使用本机查询是可以接受的,在我看来,这将是最简单、最高效的方法:

    公共接口CorporationRepo扩展了JpaRepository{
    @查询(value=“选择a.city作为城市,a.street作为地址表a中的街道,其中a.corporation\u id=?1”,nativeQuery=true)
    如下所示:

    公共接口地址投影{
    字符串getCity();
    字符串getStreet();
    默认地址到地址(){
    返回新地址(getCity(),getStreet());
    }
    }
    
    (请注意,必须在带有投影的select查询中使用别名(即
    a.city as city

    然后您将能够使用地址:

    corporationRepo.getAddressesByCorpId(corpId)
    .stream()
    .map(AddressProjection::toAddress)
    .forEach(System.out::println);
    
    如果您不能使用本机查询(我不知道为什么),您可以使用第二个选项-带有join的查询:

    公共接口CorporationRepo扩展了JpaRepo{
    @查询(value=“选择a.city作为城市,a.street作为地址表a中的街道,其中a.corporation\u id=?1”,nativeQuery=true)
    列出getAddressesByCorpId(长corpId);
    @查询(“从公司c中选择a加入c地址a,其中c.id=?1”)
    列表readAddressesByCorpId(长corpId);
    }
    
    corporationRepo.readAddressesByCorpId(corpId.forEach)(System.out::println);
    
    它将生成这样一个查询:

    选择
    a、 作为col0的城市,
    a、 街如可乐
    从…起
    c公司
    c.id=a.corporation\u id上的表a的内部联接地址
    哪里
    c、 id=1
    
    当然,它不像第一个那样是最优的,但也不是完全糟糕的,因为它只有一个索引字段的“连接”

    您的第一个选项与第二个选项相同,因为根据规范,您将得到相同的“加入”查询