Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.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
Java 带有manyTone的JPA复合键获取org.hibernate.PropertyAccessException:无法通过的反射设置器设置字段值_Java_Hibernate_Jpa_One To Many_Many To One - Fatal编程技术网

Java 带有manyTone的JPA复合键获取org.hibernate.PropertyAccessException:无法通过的反射设置器设置字段值

Java 带有manyTone的JPA复合键获取org.hibernate.PropertyAccessException:无法通过的反射设置器设置字段值,java,hibernate,jpa,one-to-many,many-to-one,Java,Hibernate,Jpa,One To Many,Many To One,我有一个复合键ContractServiceLocationPK,由三个id(contractId,locationId,serviceId)组成,类型为long,位于一个可嵌入类中。使用此复合键的类,ContractServiceLocation,使用@MapsId注释将这些ID映射到它们的对象。下面是它的样子(删除了setter/getter和不相关的属性): 合同 @Entity @Table(name = "Contract") public class Contract impleme

我有一个复合键
ContractServiceLocationPK
,由三个id(
contractId
locationId
serviceId
)组成,类型为long,位于一个可嵌入类中。使用此复合键的类,
ContractServiceLocation
,使用
@MapsId
注释将这些ID映射到它们的对象。下面是它的样子(删除了setter/getter和不相关的属性):

合同

@Entity
@Table(name = "Contract")
public class Contract implements Serializable {

    public Contract() {
    }

    @Id
    @GeneratedValue
    private long id;
    @OneToMany(mappedBy = "contract", cascade = CascadeType.ALL, fetch= FetchType.EAGER)
    Collection<ContractServiceLocation> contractServiceLocation;
}
合同服务地点

@Entity
@Table(name="Contract_Service_Location")
public class ContractServiceLocation implements Serializable {

    @EmbeddedId
    ContractServiceLocationPK id;

    @ManyToOne(cascade = CascadeType.ALL)
    @MapsId("contractId")
    Contract contract;

    @ManyToOne(cascade = CascadeType.ALL)
    @MapsId("locationId")
    Location location;

    @ManyToOne(cascade = CascadeType.ALL)
    @MapsId("serviceId")
    Service service;    

    BigDecimal price;
}
@Entity
@Table(name="Contract_Service_Location")
@IdClass(ContractServiceLocationPK.class)
public class ContractServiceLocation implements Serializable {

    @Id
    Contract contract;

    @Id
    Location location;

    @Id
    Service service;    

    BigDecimal price;
        //getters and setters
        //overridden equals() and hashCode()
}
尝试以任何方式(直接或通过契约)持久化ContractServiceLocation类型的对象时,我得到:

我的假设是JPA/Hibernate需要一个契约对象而不是一个长变量,但是如果我将Embeddeble中的变量从long更改为它们的类型,那么我得到的
关系“契约”映射的ID类型与目标实体的主键类不一致。
。如果我尝试使用id类而不是Embeddeble,那么在Contract的OneToMany映射中,我在属性“contractServiceLocation”中得到了“mappedby”,属性“Contract”的“mappedby”对此关系具有无效的映射类型。。我应该怎么做才能使复合键具有多个
manytone
映射

编辑:添加了一个片段,我尝试在其中保存项目:

    Service service = new Service();
    // Set all service properties       
    Contract contract = new Contract();
    // Set all contract properties
    Location location = new Location();
    // Set all location properties
    ContractServiceLocation csl = new ContractServiceLocation();
    csl.setContract(contract);
    csl.setLocation(location);
    csl.setService(service);
    Collection<ContractServiceLocation> cslItems = new ArrayList<>();
    cslItems.add(csl);

    em.getTransaction().begin();
    em.persist(location);
    em.persist(service);
    em.persist(csl);
    em.persist(contract);
    em.getTransaction().commit();
合同服务地点

@Entity
@Table(name="Contract_Service_Location")
public class ContractServiceLocation implements Serializable {

    @EmbeddedId
    ContractServiceLocationPK id;

    @ManyToOne(cascade = CascadeType.ALL)
    @MapsId("contractId")
    Contract contract;

    @ManyToOne(cascade = CascadeType.ALL)
    @MapsId("locationId")
    Location location;

    @ManyToOne(cascade = CascadeType.ALL)
    @MapsId("serviceId")
    Service service;    

    BigDecimal price;
}
@Entity
@Table(name="Contract_Service_Location")
@IdClass(ContractServiceLocationPK.class)
public class ContractServiceLocation implements Serializable {

    @Id
    Contract contract;

    @Id
    Location location;

    @Id
    Service service;    

    BigDecimal price;
        //getters and setters
        //overridden equals() and hashCode()
}

目前看来,这是正确的。它创建一个复合键,并与所有复合属性保持多对一关系。然而,有一些奇怪的事情。在带有属性“ContractServiceLocation”中错误消息的
ContractServiceLocation
集合的
@OneToMany
注释上的Contract eclipse标记
mappedBy
中,“mappedBy”属性“Contract”对此关系具有无效的映射类型。。我假设这是因为
ContractServiceLocation
中定义的
Contract
属性没有
@manytone
注释,而是在复合类中定义的。我是不是偶然发现了“不兼容JPA但使用Hibernate”的陷阱,或者这里发生了什么事?

您需要将getter和setter也放在@Embeddeble类中,您的hashCode()和equals()方法将放在我在这里发布的类中看不到的类中

为了保存ContractServiceLocation,需要首先保存以下对象,因为您使用它们的ID作为ContractServiceLocation的复合键,对吗?在这里,您要做的是将这些对象创建为新对象,以便它们显然没有id,因为它们没有持久化。因此,您需要首先持久化它们,然后使用持久化对象并将对象设置到ContractServiceLocation中

    Service service = new Service();
    // Set all service properties       
    Contract contract = new Contract();
    // Set all contract properties
    Location location = new Location();
    // Set all location properties

对于原始问题(非修改变量):

您必须在ContractServiceLocation类中安装“ContractServiceLocationPK id”。替换行:

@嵌入ID ContractServiceLocationPK id

为此:

@嵌入ID ContractServiceLocationPK id=新ContractServiceLocationPK()


那么它应该会起作用。因为Hibernate试图在内部设置属性,但在NullPointerException上失败。

如果您使用
ContractServiceLocation
的构造函数初始化
ContractServiceLocationPK
很高兴我找到了这个问题和答案,那么它也可以工作。这是相当“令人惊讶的”。例如,EclipseLink 2.6.4在相同的上下文中运行良好。谢谢。可怕的情况是,如此重要和有价值的库hibernate忽略了与联接表中附加字段的多对多关系。这是一个核心的、基本的RDBMS设计组件。人们必须创建一个嵌入式id(别忘了实例化它)并经历如此多的诡计才能让它工作,这是不真实的。这是典型的hibernate和对Java如此痴迷的社区,在本例中,它忽略了RDBMS的基础知识……在3天的搜索和阅读之后(并验证这是我的案例)。内部尖叫
    Service service = new Service();
    // Set all service properties       
    Contract contract = new Contract();
    // Set all contract properties
    Location location = new Location();
    // Set all location properties