问题
I cannot cascade merge with persist three levels of entities using @EmbeddedId
in the last entity. I have three following entities:
1. Voucher
2. Rate
3. RatePerChannelOverwrite
The Voucher
is fetched by a service. Then I want to add new Rate
to the voucher. Then I want to add new RatePerChannelOverwrite
to the Rate
. So both Rate
and RatePerChannelOverwrite
will have their @Id
as NULL. This is working.
However later I tried to split RatePerChannelOverwrite
into two classes and have: @Embeddable RatePerChannelOverwriteId
. And this setup is failing. The Rate
referened by RatePerChannelOverwriteId
never gets its new ID populated.
@Entity
public class Voucher {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Integer id;
@OneToMany(mappedBy = "voucher", fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL)
private Set<Rate> rates = new HashSet<Rate>();
}
@Entity
public class Rate {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "voucher_id", referencedColumnName = "id")
private Voucher voucher;
@Column(name = "rate", precision = 2, scale = 9, columnDefinition = "decimal")
@NumberFormat(pattern = "#0.00")
private double rate;
@OneToMany(mappedBy = "rate", fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.ALL)
private Set<RatePerChannelOverwrite> ratePerChannelOverwrites;
}
@Entity
public class RatePerChannelOverwrite {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Integer id;
@ManyToOne
@JoinColumn(name = "rate_id", referencedColumnName = "id")
private Rate rate;
@Column(name = "channel_id")
private Integer channelId;
@Column(name = "rate", precision = 2, scale = 9, columnDefinition = "decimal")
@NumberFormat(pattern = "#0.00")
private double rate;
}
And this works fine when I do something like that:
Voucher voucher = service.getVoucher(123456);
Rate rate = new Rate(); //NOTE ID IS NULL HERE
rate.setVoucher(voucher);
voucher.getRates().add(rate);
RatePerChannelOverwrite channelRate = new RatePerChannelOverwrite();
channelRate.setRate(rate);
rate.getRatePerChannelOverwrites.add(channelRate);
voucher = voucher.merge();
However when I separate last entity into 2 separate classes, then the id
of rate
in RatePerChannelOverwriteId
is ALWAYS NULL. Somehow cascading here fails.
NOTE: Third entity has composite key as @EmbeddedId
with @ManyToOne
, and this is where the problem shows up.
@Embeddable
public class RatePerChannelOverwriteId {
@ManyToOne
@JoinColumn(name = "rate_id", referencedColumnName = "id")
private Rate rate;
@Column(name = "channel_id")
private Integer channelId;
}
@Entity
public class RatePerChannelOverwrite {
@EmbeddedId
private RatePerChannelOverwriteId id;
@Column(name = "rate", precision = 2, scale = 9, columnDefinition = "decimal")
@NumberFormat(pattern = "#0.00")
private double rate;
}
Is it correct to do this?
Voucher voucher = service.getVoucher(123456);
Rate rate = new Rate();
rate.setVoucher(voucher);
voucher.getRates().add(rate);
RatePerChannelOverwriteId channelRateId = new RatePerChannelOverwriteId();
channelRateId.setRate(rate);
RatePerChannelOverwrite channelRate = new RatePerChannelOverwrite();
channelRate.setId(channelRateId);
rate.getRatePerChannelOverwrites.add(channelRate);
voucher = voucher.merge();
The actual exception I get is NullPointer from 'org.hibernate.type.descriptor.AbstractTypeDescriptor.extractHashCode(T value)' where value is NULL, because id
in Rate
is still NULL (although SQL trace shows INSERT was performed on Rate
).
来源:https://stackoverflow.com/questions/42217331/hibernate-nullpointer-on-inserted-id-when-persisting-three-levels-using-embedda