i具有一个复合键
ContractServiceLocationPK
iD在可嵌入类中的三个ID(contractId
,locationId
,serviceId
)制成。使用此复合键的类,使用ContractServiceLocation
注释将这些ID映射到其对象。以下是看起来像(删除的设定器/getters和无关紧要的属性):收缩
@MapsId
ContractserviceLocationpk
@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;
}
ContractservIceLocation
@Embeddable
public class ContractServiceLocationPK implements Serializable {
private long contractId;
private long locationId;
private long serviceId;
}
试图以任何方式(直接或通过合同)坚持类型合同的对象时,我会得到:
@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;
}
我的假设是JPA/Hibernate期望合同对象而不是一个长变量,但是如果我将嵌入式中的变量从长时间更改为它们的类型,那么我会得到
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.test.model.ContractServiceLocationPK.contractId
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1187)
at com.test.MainTest.main(MainTest.java:139)
Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of com.test.model.ContractServiceLocationPK.contractId
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:134)
at org.hibernate.mapping.Component$ValueGenerationPlan.execute(Component.java:441)
at org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:121)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:117)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
... 1 more
Caused by: java.lang.NullPointerException
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source)
at sun.reflect.UnsafeLongFieldAccessorImpl.set(Unknown Source)
at java.lang.reflect.Field.set(Unknown Source)
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:122)
... 12 more
。如果我尝试使用ID类而不是嵌入式类别,则在合同的OneTomany映射中,我会得到。我该怎么做才能制作一个具有多个映射的复合键?
Edit:
添加了一个片段,我试图坚持这些项目:
The type of the ID mapped by the relationship 'contract' does not agree with the primary key class of the target entity.
看起来像这样而不是在某个dao中的原因是因为我正在生成数据库并在开发其余的应用程序之前先对项目进行测试。
Edit2:我已经重写了我的模型,现在一切似乎都起作用,除了Eclipse我会持续存在错误。以下是当前的外观:
合同 - 没有更改(除了删除急切的加载) ContractserviceLocationpk-现在是ID类
mappedby
ContractservIceLocation
In attribute 'contractServiceLocation', the "mapped by" attribute 'contract' has an invalid mapping type for this relationship.
目前似乎可以正常工作。它创建一个复合键,并与所有复合属性保持多一关系。但是有些奇怪。在Contract Eclipse中标记
ManyToOne
在带有错误消息的
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();
收集的注释上。我假设这是因为
public class ContractServiceLocationPK implements Serializable {
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "contract_id")
private Contract contract;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "location_id")
private Location location;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "service_id")
private Service service;
//getters and setters
//overridden equals() and hashCode()
}
中定义的
@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()
}
属性没有
mappedBy
注释,但是在复合类中定义了
@OneToMany
属性。我是否偶然发现了“不合规的JPA,但使用Hibernate”陷阱还是在这里发生了什么?
对于您的原始问题(未修改的变体):您必须在您的合同服务授权类中进行“ ContractServiceLocationpk ID”进行启动。更换行:
@embeddedid ContractServiceLocationpk ID;
this:
@embeddedid ContractServiceLocationpk ID =新ContractServicElocationpk(); 然后应该有效。因为Hibernate试图在内部设置属性,但在NullPoInterException上失败。
为了保存合同服务的命令,需要首先保存以下对象,因为您将其ID用作合同服务员的复合密钥,对吗?在这里,您正在做的是,您正在将它们作为新对象创建,因此显然它们不会拥有其ID,因为它们不坚持。因此,您需要首先持续使用它们,并使用持久的对象并将对象设置为ContractServiceLocation。
ContractServiceLocation
ContractServiceLocation constructor为加入实体创建新实例时,应手动初始化@embeddedid复合主键字段,因为Hibernate无法通过反射设置该值
我在项目中也有同样的问题,我更改的唯一一件事就是在实体类中创建一个嵌入式的实例。看起来像这样。在一切都变得完美时,我不是春季和爪哇的专家,所以它可能在我不知道的代码中的其他地方产生一些后果。@embeddedid listyHotelikey id = new ListyHotelikey();