tags:

views:

581

answers:

3

I'm running into a strange problem using the Toplink implementation of JPA. I'm writing a stand-alone application to manage loans.

I define a LOAN class that has a OneToMany (bi-directional) relationship with a NOTICE class. I created a GUI to display all the notices for a particular loan. In another part of my program I can send out late notices which is saved as a NOTICE. However, when I try to display all the notices for a loan, the late notice is NOT appearing. I've checked the database and an entry has been saved but for some reason the notice is not being pulled.

Only when I restart my application does the notice appear.

Because I've defined a OneToMany relationship, I, myself, am not making a "direct" query into the database - I'm letting JPA handle retrieving all the notices for me.

As a fix, I created a query to simply get all notices for a particular loan. This works. However, I thought by defining the OneToMany relationship between the two classes, this should be handled for me. It seems like something is not being refreshed properly... as if an "older" list of notices is being used instead of refreshing from the database?

A: 

Hi,

I suppose the following

@Entity
public class Loan {

    private Integer id;

    private List<Notice> noticeList;

    @Id
    @GeneratedValue
    public Integer getId() {
        return this.id;
    }

    @OneToMany(mappedBy="loan")
    public List<Notice> getNoticeList() {
        return noticeList;
    }

}

@Entity
public class Notice {

    private Integer id;

    private Loan loan;

    @Id
    @GeneratedValue
    public Integer getId() {
        return this.id;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    public Loan getLoan() {
        return this.loan;
    }

}

You have said

In another part of my program I can send out late notices which is saved as a NOTICE

Maybe you have two EntityManager instances (one for each part of your program) so the last Notice saved is not showed because both entityManager does not share the same persistence context (One is not aware of the changes occured in the other). What you can do is clear your persistence context and then retrieve it again as follows

In anther part of your program (after persisting your Notice) call

entityManager.flush();

And when you want to retrive a Loan and its Notice

entityManager.clear();

Query query = entityManager.creatQuery("from Loan l left join fetch l.noticeList where l.id = :id");

query.setParameter("id", yourLoanId);

Check it out and tell me whether it works fine.

regards,

Arthur Ronald F D Garcia
The Loan and Notice entity classes you describe above are pretty much the same as how I coded them up. My initial work-around to my problem was to create a Query as you describe above however I didn't understand why doing - MyLoanInstance.getNoticeList() was not giving me the same results as doing the query directly. I do think its a "refresh" problem related two entityManager instances as you describe above... however, I was able to solve the problem with Tnay's suggestion.
Andre
A: 

Have you tried to do a flush on your entity manager after you have persisted the NOTICE ? [ entityManager.flush() ]

ChristiaanP
+2  A: 

How are you 'sending the late notice'? There needs to be a statement similar to:

MyLoanInstance.listOfNotices.add(MyNoticeInstance);

even if you already have a

MyNoticeInstance.setLoan(MyLoanInstance);

statement

Without that call, you will have to either completely reload the instance you are working with, or restart your application.

Eclipselink does not automatically update (until reloading everything) the collection on the M side of a 1:M relationship when you modify the 1 side, nor does it update the reference in the 1 side of the 1:M relationship if you modify the collection in the M side.

As a side note, you should consider checking out EclipseLink, it evolved out of what was TopLink, you should be able to directly swap the EclipseLink .jar with the TopLink .jar, if only to recieve a few depreciation warnings.

Eclipse Link

instanceofTom
This worked! When "sending out a late notice," I was only taking care of one side of the 1:M relationship - as you mention above. However, when I load the loan to view the different notices that went out, I thought I was "completely reloading the instance." Perhaps I need to take a closer look at my code when I load the loan instance.
Andre
@instanceofTom: Thanks - saved my day!
Hank