La colección perezosa se inicializó con entusiasmo (transaccional + carga diferida)

La clase de ciudad se asigna a la base de datos.

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


}

Capa Dao para 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;
    }
}

Prueba:

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);
    }

}

contexto raíz:

<?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>

Cuando estoy usando el método 'getCityById()' en mi 'LazyTest()' en el modo de depuración, obtengo un resultado extraño. En la depuración, veo que mi colección de eventos se inicializó antes de usarla por primera vez. Pero estoy usando Lazy Fetch Strategy. ¿Lo que está mal?

preguntado el 04 de julio de 12 a las 08:07

1 Respuestas

Eso es porque ya está en la sesión. Load devuelve el objeto City que acaba de crear, sin obtenerlo de la base de datos.

Agregue el siguiente código antes de la llamada getCityById: obtendrá el resultado que espera.

sessionFactory.getCurrentSession().flush()
sessionFactory.getCurrentSession().clear()

Respondido 04 Jul 12, 11:07

¿Puedes aceptar la respuesta? meta.stackexchange.com/questions/5234/… - gkamal

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.