In my case, I have an AcctgEntry object that has a list of AcctgLine objects as an attribute.
public class AcctgEntry{ @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "GL_TRANS_HEADER_SEQ_GEN") @Column(name = "GL_TRANS_HEADER_ID", nullable = false) private Long id; @OneToMany(mappedBy = "acctgEntry", cascade = CascadeType.ALL) private List<AcctgLine> acctgLineList = new ArrayList<AcctgLine>(); //plus other attributes //plus getters and setters //plus other relevant methods }
public class AcctgLine{ @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "GL_TRANS_DETAIL_SEQ_GEN") @Column(name = "GL_TRANS_DETAIL_ID", nullable = false) private Long id; @Column(name = "LINE_NO", nullable = false) private Long lineNo; @ManyToOne @JoinColumn(name = "GL_NATURAL_ACCT_ID", nullable = false) private NaturalAcct naturalAcct; @ManyToOne @JoinColumn(name = "GL_TRANS_HEADER_ID") private AcctgEntry acctgEntry; //plus other attributes //plus getters and setters //plus other relevant methods }
AcctgEntry objects can be created, saved and can be edited multiple times as long as the entry is not yet posted. My web interface is bound to a model which is queried from a stateless session bean. In this scenario, my model object is in detached state.
Sample case:
A user created an entry with the following AcctgLine objects:
acctgEntry JV#001 -acctgLine1 DR100 -acctgLine2 CR100When the user invoked Save, my service class verify if the Debit and Credit are balanced, and indeed it is, so the the entry was persisted to the database.
Now the problem is this. The user edited the acctgEntry, he removed the -acctgLine2 and and added two additional acctgLines as follows:
acctgEntry JV#001 -acctgLine1 DR100 -acctgLine3 CR50 -acctgLine4 CR50The user again invoked Save and my service class verify if the entry is balanced and and again succeeded, so the entry was merged to the database. But when I requery the acctgEntry that was updated, it has now as follows:
acctgEntry JV#001 -acctgLine1 DR100 -acctgLine2 CR100 -acctgLine3 CR50 -acctgLine4 CR50I was puzzled because the -acctgLine2 was not removed from the database, and now my entry is imbalanced (Total debits 100, but the totals credits is 200).
I check on the internet and noted that this is a valid behavior based on the jpa specification. You can read the discussion here: JPA OneToMany not deleting child
With further research, I am happy to solved my issue with just a single additional persistence annotation- @PrivateOwned. More about this annotation here: How to Use the @PrivateOwned Annotation. With this annotation, whenever acctgLines were removed from the AcctgLine list attribute on my AcctgEntry object, the changes will be synchronized to the database upon merge.
My AcctgEntry class is now something like below:
public class AcctgEntry{ @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "GL_TRANS_HEADER_SEQ_GEN") @Column(name = "GL_TRANS_HEADER_ID", nullable = false) private Long id; @PrivateOwned @OneToMany(mappedBy = "acctgEntry", cascade = CascadeType.ALL) private List<AcctgLine> acctgLineList = new ArrayList<AcctgLine>(); //plus other attributes //plus getters and setters //plus other relevant methods }
Cheers!
No comments:
Post a Comment