City クラスはデータベースにマップされます。
@Entity
@Table(name = "City")
public class City implements Serializable, IRelationsQualifier
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
//-------------------------------------------------------
@JsonIgnore
@NotFound(action = NotFoundAction.IGNORE)
@ManyToMany(
fetch = FetchType.LAZY,
cascade = {CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},
targetEntity = Event.class
)
@JoinTable(
name="CityEvent",
joinColumns = @JoinColumn( name="city_id"),
inverseJoinColumns = @JoinColumn( name="event_id")
)
private Set<Event> eventList = new HashSet<Event>();
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
@JsonIgnore
public Set<Event> getEvents()
{
return eventList;
}
@JsonIgnore
public void setEvents(Set<Event> events)
{
this.eventList = events;
}
}
都市の Dao レイヤー。
package com.globerry.project.dao;
// removing imports to make it easier to read
@Repository
public class CityDao implements ICityDao
{
@Autowired
SessionFactory sessionFactory;
@Autowired
@Override
public City getCityById(int id)
{
City city = (City) sessionFactory.getCurrentSession().load(City.class, id);
return city;
}
}
テスト:
package com.globerry.project.dao;
// removing time imports to make it easier to read.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/META-INF/spring/daoTestContext.xml")
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class, ContextLoaderListener.class
})
public class CityDaoTest {
@Test
@Transactional(readOnly=false)
public void LazyTest()
{
City city1 = new City();
city1.setName("Bobryjsk1");
try
{
cityDao.addCity(city1);
}
catch (MySqlException e)
{
e.printStackTrace(System.err);
}
Event ev = new Event();
ev.setName("Disnayland");
eventDao.addEvent(ev, city1);
ev = new Event();
ev.setName("Disnayland5");
eventDao.addEvent(ev, city1);
System.err.println("1");
city1 = cityDao.getCityById(city1.getId());//there i saw in debug that events have been already inizialized
System.err.println("2");
System.err.println(Hibernate.isInitialized(city1.getEvents()));//returns true
Iterator<Event> it = city1.getEvents().iterator();
System.err.println("3");
ev = it.next();
System.err.println(ev.getName());
ev = new Event();
ev.setName("Disnayland55");
eventDao.addEvent(ev, city1);
}
}
ルートコンテキスト:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- <jdbc:embedded-database id="dataSource" type="H2"/> -->
<context:annotation-config />
<context:component-scan base-package="com.globerry.project.domain" />
<context:component-scan base-package="com.globerry.project.dao" />
<context:component-scan base-package="com.globerry.project.service" />
<!-- Файл с настройками ресурсов для работы с данными (Data Access Resources) -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Менеджер транзакций -->
<!-- Настройки бина dataSource будем хранить в отдельном файле -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:/META-INF/jdbc.properties" />
<!-- Непосредственно бин dataSource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="${jdbc.databaseurl}"
p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<!-- Настройки фабрики сессий Хибернейта -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:packagesToScan="com.globerry.project.Dao">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory">
<qualifier value="transactionManager"/>
</bean>
</beans>
デバッグ モードの「LazyTest()」でメソッド「getCityById()」を使用すると、奇妙な結果が得られます。デバッグでは、初めて使用する前に、イベント コレクションが初期化されていることがわかります。しかし、私はレイジーフェッチ戦略を使用しています。なにが問題ですか?