City class is mapped to database.
@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 layer for City.
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;
}
}
Test:
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);
}
}
root-context:
<?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>
When I’m using method ‘getCityById()’ in my ‘LazyTest()’ in debug mode I get strange result. In debug i see that my event collection was initialized, before I use it for the first time. But I’m using Lazy Fetch Strategy. What is wrong?
That is because it is already in the session. Load returns the City object that you just created – not fetching it from the database.
Add the following code before the getCityById call – you will get the result you are expecting.