У меня проблема. Я изучаю JPA. Я использую встроенный OpenEJB контейнер в модульных тестах, но работает только @OneToMany(fetch=EAGER)
. В противном случае коллекция всегда пуста. Я не нашел, как работает ленивая стратегия, как контейнер заполняет данные и при каких обстоятельствах запускает действие загрузки контейнера?
Я прочитал, что действие срабатывает, когда вызывается геттер. Но когда у меня есть код:
@OneToMany(fetch = LAZY, mappedBy="someField")
private Set<AnotherEntities> entities = new Set<AnotherEntities>();
...
public Set<AnotherEntities> getEntities() {
return entities;
}
Я всегда получаю ноль. Я считаю, что стратегию LAZY нельзя протестировать с помощью встроенного контейнера. Проблема может быть также в двунаправленном отношении.
Есть ли у кого-нибудь еще подобные опыты с тестированием JPA?
Вложения
Реальный контрольный пример с настройкой:
@RunWith(UnitilsJUnit4TestClassRunner.class)
@DataSet("dataSource.xml")
public class UnitilsCheck extends UnitilsJUnit4 {
private Persister prs;
public UnitilsCheck() {
Throwable err = null;
try {
Class.forName("org.hsqldb.jdbcDriver").newInstance();
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
props.put("ds", "new://Resource?type=DataSource");
props.put("ds.JdbcDriver", "org.hsqldb.jdbcDriver");
props.put("ds.JdbcUrl", "jdbc:hsqldb:mem:PhoneBookDB");
props.put("ds.UserName", "sa");
props.put("ds.Password", "");
props.put("ds.JtaManaged", "true");
Context context = new InitialContext(props);
prs = (Persister) context.lookup("PersisterImplRemote");
}
catch (Throwable e) {
e.printStackTrace();
err = e;
}
TestCase.assertNull(err);
}
@Test
public void obtainNickNamesLazily() {
TestCase.assertNotNull(prs);
PersistableObject po = prs.findByPrimaryKey("Ferenc");
TestCase.assertNotNull(po);
Collection<NickNames> nicks = po.getNickNames();
TestCase.assertNotNull(nicks);
TestCase.assertEquals("[Nick name: Kutyafája, belongs to Ferenc]", nicks.toString());
}
}
Бин Presister
- это бин, опосредующий доступ к бинам сущностей. Важный код класса следует:
@PersistenceUnit(unitName="PhonePU")
protected EntityManagerFactory emf;
public PhoneBook findByPrimaryKey(String name) {
EntityManager em = emf.createEntityManager();
PhoneBook phonebook = (PhoneBook)em.find(PhoneBook.class, name);
em.close();
return phonebook;
}
Entity PhoneBook
- это одна строка телефонной книги (также лицо). Один человек может иметь ноль или более псевдонимов. Со стратегией EAGER это работает. С LAZY коллекция всегда нулевая. Может быть проблема в отрыве предметов. (См. OpenEJB - JPA Concepts , часть Кэши и отсоединение.) Но в руководстве написано, что коллекция может быть иногда (больше как много раз) пустой, но не нулевой.