EJB, JPA и @OneToMany - транзакция слишком длинная? - PullRequest
1 голос
/ 07 декабря 2009

Я использую EJB и JPA, и когда я пытаюсь получить доступ к PhoneNumber объектам в phoneNumbers атрибуте Contact contact, иногда это может занять несколько минут, чтобы он действительно вернул данные. Он просто не возвращает никаких телефонных номеров, даже нулевых, а затем, через некоторое время, когда я снова его вызываю, он волшебным образом появляется.

Вот так я получаю доступ к данным:

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

Я использую сессионный фасад ejb, сгенерированный netbeans (основные методы CRUD). Он всегда печатает правильное имя и фамилию, номера телефонов и описание печатаются только через некоторое время (меняется) от его создания через фасад. Я предполагаю, что это как-то связано с транзакциями. Как это решить?

Это мои объекты JPA:

контакт

@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;

Ответы [ 3 ]

0 голосов
/ 24 августа 2010

проверьте генерируемый SQL и попытайтесь увидеть на БД время, которое они занимают ... когда они запускаются в консоли прямо на БД! если ваш SQL работает с плохо настроенной БД ... ничего не поможет.

0 голосов
/ 24 августа 2010

Учитывая ваше фактическое сопоставление, я думаю, что ваш код фактически выполняет N + 1 запросов (1 запрос для загрузки N Contact и затем 1 запрос на контакт для загрузки его PhoneNumber) и в зависимости от количества Contact, это может быстро стать очень неэффективным. Хорошей идеей здесь может быть активная загрузка ассоциации (с помощью FETCH JOIN).

Активация ведения журнала сгенерированного SQL позволит, по крайней мере, подтвердить это поведение и точно увидеть, что происходит. Добавление некоторых операторов журнала, окружающих цикл (ы), также поможет увидеть, на что тратится время. И если где-то есть проблемы с транзакциями, они также должны быть видны в журналах.

Это, на самом деле, моя главная мысль: если вы хотите что-то улучшить, вам нужно сначала измерить . Без каких-либо мер вы просто делаете несколько снимков в темноте.

Если вы не можете измерить это, вы не можете улучшить его. - Лорд Кельвин

0 голосов
/ 07 декабря 2009

Вы пробовали использовать

fetch = FetchType.EAGER

за ваши отношения с OneToMany?

...