Reputation: 511
We have a Java ee application running on JBoss 6.4 GA using JPA and Hibernate with the following entities:
@Entity
@SequenceGenerator(name = "sequence", sequenceName="SEQ_CAMPAIGNS_ID",allocationSize = 1)
@Table(name = "CAMPAIGN")
public class CampaignEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
@Column(name = "ID")
private Long id;
@Column(name = "NAME")
private String name;
@Column(name = "IS_ACTIVE", nullable = false)
private boolean active;
@Column(name = "START_DATE", nullable = false)
private Date startDate;
@Column(name = "END_DATE", nullable = false)
private Date endDate;
@Column(name = "LEGAL_ENTITY_ID", nullable = false)
private Integer legalEntityId;
@Column(name = "DEPARTMENT", nullable = false)
@Enumerated(value = EnumType.STRING)
private Department department;
@Column(name = "CATEGORY", nullable = false)
@Enumerated(value = EnumType.STRING)
private Category category;
@Embedded
CampaignConditionsEntity campaignConditions;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "campaign", orphanRemoval = true)
@OrderBy
private List<CodeEntity> campaignCodes;
public CampaignEntity() {
}
And the following CampaignConditionsEntity:
@Embeddable
public class CampaignConditionsEntity implements Serializable {
private static final String CAMPAIGN_ID = "CAMPAIGN_ID";
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "CAMPAIGN_COND_TRIP_TYPE", joinColumns = @JoinColumn(name = CAMPAIGN_ID))
private Set<TripTypeConditionEntity> tripTypeConditions;
And the following CodeEntity:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@SequenceGenerator(name = "sequence", sequenceName = "SEQ_CODES_ID", allocationSize = 1)
public abstract class CodeEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
@Column(name = "ID", nullable = false)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CAMPAIGN_ID")
private CampaignEntity campaign;
@OneToOne(mappedBy = "code", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false, orphanRemoval = true)
private DiscountEntity discount;
@Column(name = "MAX_USAGES", nullable = false)
private Integer maxUsages;
@Column(name = "UNLIMITED_USAGES", nullable = false)
private boolean unlimitedUsages;
@Column(name = "NEGATIVE_SH", nullable = false)
private boolean negativeSH;
@Column(name = "UNIQUE_BUYER", nullable = false)
private boolean uniqueBuyer;
@Column(name = "START_DATE")
private Date startDate;
@Column(name = "END_DATE")
private Date endDate;
@Embedded
private CodeConditionsEntity codeConditions;
public CodeEntity() {
}
This is the CodeConditionsEntity:
@Embeddable
public class CodeConditionsEntity implements Serializable {
private static final String CODE_ID = "CODE_ID";
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "CODE_COND_TRIP_TYPE", joinColumns = @JoinColumn(name = CODE_ID))
private Set<TripTypeConditionEntity> tripTypeConditions;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "CODE_COND_CARRIERS", joinColumns = @JoinColumn(name = CODE_ID))
private Set<CarrierConditionEntity> carrierConditions;
This is the CarrierConditionEntity:
@Embeddable
public class CarrierConditionEntity implements Serializable {
@Column(name = "CARRIER", nullable = false, length = 3)
private String carrierCode;
@Column(name = "IS_INCLUDED", nullable = false)
private boolean included;
The problem is that in the logs we are finding unexpected deletes when the only operation that we are doing are finds of particular campaign entities.
In the production logs we find the following deletes
Hibernate: delete from CODE_COND_CARRIERS where CODE_ID=? and CARRIER=? and IS_INCLUDED=?
do you have any suggestion?
thanks
Upvotes: 1
Views: 105
Reputation: 511
I found where was the problem:
The problem was that the Entities didn't have the equals() and the hashcode() implemented. Also there were entities that have a @PostLoad that modified the entity after loading it from database. Then in this situation Hibernate though that there was a change in those entities that didn't have the equals and the hashcode, and then it delete all of them and inserted again in the database (to have the same entities before the query) Adding the equals and hashcode methods and deleting postload removed the unexpected deletes and inserts from the logs.
regards
Upvotes: 2
Reputation: 8323
I have some suggestions :)
Be aware of what is a Persistence Context
(EntityManager
instance in JPA terminology / Session
in Hibernate one), the entity lifecycle and transaction scope (unit of work)
Do not mutate entity state if you don't expect the changes to be reflected in database, or at least detach the entity before mutating it.
Mark your transaction as "readOnly
" if you only fetch data in the related unit of work. (beware that if you have many "Transactional" methods joining the same physical transaction, the flag is set by the surrounding one and cannot be overridden by inner logical transactions). That way the EntityManager
won't be flushed at the end of the transaction and pending changes won't be persisted to the database.
You can track the method triggering the unexpected deletion using an EntityListener
on the related entity and printing the current strackTrace (new Throwable().printStackTrace()
/ log(new Throwable()
) in the PreRemove
method
Upvotes: 1