tags:

views:

199

answers:

3

Hello. I'm using EJB and JPA, and when I try to access PhoneNumber objects in phoneNumbers attribute of Contact contact, it sometimes take several minutes for it to actually return data. It just returns no phoneNumbers, not even null, and then, after some time, when i call it again, it magically appears.

This is how I access data:

for (Contact c : contactFacade.findAll()) {
    System.out.print(c.getName()+" "+c.getSurname()+" : ");
    for (PhoneNumber pn : c.getPhoneNumbers()) {
        System.out.print(pn.getNumber()+" ("+pn.getDescription()+"); ");
    }
}

I'm using facade session ejb generated by netbeans (basic CRUD methods). It always prints correct name and surname, phonenumbers and description are only printed after some time (it varies) from creating it via facade. I'm guessing it has something to do with transactions. How to solve this?

These are my JPA entities:

contact

@Entity public class Contact implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String surname;
    @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "contact")
    private Collection<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();

phonenumber

@Entity
public class PhoneNumber implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String number;
    private String description;
    @ManyToOne()
    @JoinColumn(name="CONTACT_ID")
    private Contact contact;
A: 

Have you tried using

fetch = FetchType.EAGER

for your OneToMany relationship?

djna
No, but I just tried it and it doesn't work.
marioErr
A: 

check the SQL that are generated and try to see on the DB the time they take ...when hey are run in a console directly against the DB ! if yr SQL are ran against a badly tuned DB ... nothing will help.

Thomas
A: 

Given your actually mapping, I think that that your code is actually performing N+1 requests (1 query to load the N Contact and then 1 query per contact to load its PhoneNumber) and depending on the number of Contact, this can become quickly very inefficient. Eagerly loading the association might be a good idea here (using a FETCH JOIN).

Activating logging of the generated SQL would at least allow to confirm this behavior and to see what is happening exactly. Adding some log statements surrounding the loop(s) would also help to see where the time is spent. And if there is a problem with transactions somewhere, they should also be visible in the logs.

This actually my main point: if you want to be able to improve something, you need to start measuring it first. Without any measures, you're just making some shots in the dark.

If you cannot measure it, you cannot improve it. --Lord Kelvin

Pascal Thivent