正如标题所说。我有一个带有复合键的实体。该实体是:
ContractServiceLocation.java
@Entity
@Table(name="CONTRACT_SERVICE_LOCATION")
@NamedQuery(name="ContractServiceLocation.findAll", query="SELECT c FROM ContractServiceLocation c")
@TypeDef(defaultForType= LocalDate.class, typeClass = LocalDateType.class)
public class ContractServiceLocation implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private ContractServiceLocationPK id;
@Column(nullable=false)
private LocalDate datefrom;
private LocalDate dateto;
@Column(length=90)
private String details;
@Column(nullable=false, precision=65535, scale=32767)
private BigDecimal price;
//bi-directional many-to-one association to Contract
@ManyToOne
@JoinColumn(name="CONTRACT_ID", nullable=false, insertable=false, updatable=false)
private Contract contract;
//uni-directional many-to-one association to Location
@ManyToOne
@JoinColumn(name="LOCATION_ID", nullable=false, insertable=false, updatable=false)
private Location location;
//uni-directional many-to-one association to Service
@ManyToOne
@JoinColumn(name="SERVICE_ID", nullable=false, insertable=false, updatable=false)
private Service service;
//getters & setters
}
ContractServiceLocationPK.java
@Embeddable
public class ContractServiceLocationPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(name="CONTRACT_ID", insertable=false, updatable=false, unique=true, nullable=false)
private long contractId;
@Column(name="LOCATION_ID", insertable=false, updatable=false, unique=true, nullable=false)
private long locationId;
@Column(name="SERVICE_ID", insertable=false, updatable=false, unique=true, nullable=false)
private long serviceId;
//getters & setters & equals & hashcode
}
由于我将JpaRepository用于所有其他实体,我认为它支持具有复合键的实体。所以我把Dao定义为:
ContractServiceLocationDao.java
@Repository
public interface ContractServiceLocationDao extends
JpaRepository<ContractServiceLocation, ContractServiceLocationPK> {
}
但是,在ContractServiceLocation实体上调用save方法后,我得到一个:
org.springframework.orm.jpa.JpaSystemException: null id generated for:class hr.kingict.telco.model.ContractServiceLocation; nested exception is org.hibernate.id.IdentifierGenerationException: null id generated for:class hr.kingict.telco.model.ContractServiceLocation
我在调试中检查过所有复合键属性(合同,服务和位置)都不为空。但是例外情况说&#34; null id 为类生成 ...&#34;所以我假设它以某种方式尝试生成一个id(即使我没有设置@GeneratedValue注释)。
我该怎么做才能解决这个问题?我是否必须手动编写dao而不是依赖JpaRepository?
答案 0 :(得分:0)
我明白了。问题是,当我向实体添加合同,服务或位置时,我没有更新id对象以反映这一点。一旦我发现解决方案很简单。在具有组合键的实体(在我的案例中为ContractServiceLocation.java)中,对于构成组合键的属性的setter,我添加了这段代码:
public void setContract(Contract contract) {
this.contract = contract;
this.id.setContractId(contract.getId()); //added line
}
所以每次我设置/更改复合属性时,id都会反映出来。
这也不完美(但现在有效),可以通过检查属性id是否为null / default以及是否抛出异常来改进。