0

I have a problems with hibernate in my Spring application. I think that there must be bad configuration.

hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/cloud_app?autoReconnect=true</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.release_mode">after_transaction</property>
        <property name="show_sql">true</property>

    ...

persistanceContext.xml

<bean id="dataSource" destroy-method="close"
        class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/cloud_app" />
        <property name="user" value="root" />
        <property name="password" value="root" />
        <property name="debugUnreturnedConnectionStackTraces" value="true" />
        <property name="unreturnedConnectionTimeout" value="20" />
        <property name="minPoolSize" value="5" />
        <property name="initialPoolSize" value="10" />
        <property name="maxPoolSize" value="50" />
        <property name="maxStatements" value="50" />
        <property name="idleConnectionTestPeriod" value="120" />
        <property name="maxIdleTime" value="1200" />
    </bean>

    <!-- Hibernate -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <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.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <!-- Transaction manager -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
        <property name="dataSource" ref="dataSource" />
    </bean>

When I use in my application sessionFactory.getCurrentSession(), it still throws the exception

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

But when I use sessionFactory.openSession(), it solves problems, but makes another issues. So my question is, how can I reach a state - one session for whole application. How reach that when I call sessionFactory.getCurrentSession(), session will be exist. I am confused, I read a lot of threads how to solve it, but without no success.

UPDATE When I get some object and then I try to change it

Opportunity opportunity = opportunityDao.get(idOpportunity);
opportunity.setOrder(order);
opportunityDao.edit(opportunity);

code from get method

public T get(Integer id) {
    T object = (T) sessionFactory.getCurrentSession().get(clazz, id);
    return object;
}

code from edit method

public void edit(T object) {
    this.sessionFactory.getCurrentSession().update(object);
}

It throws me org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

misco
  • 1,912
  • 4
  • 41
  • 68

1 Answers1

1

A couple of things

  1. Your hibernate.connection.* properties are useless as you are injecting a DataSource inside your spring application
  2. The other properties for dialect and show_sql are already set in the spring configuration, so in short (due to 1 and 2) you can delete the hibernate.cfg.xml file.
  3. Use the the AnnotationSessionFactoryBean convenience class.

Leaving you with this

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.bytecode.use_reflection_optimize">false</prop>
        </props>
    </property>
    <property name="packagesToScan" value="your.package.with.entities.here" />
</bean>

That at least cleans up your configuration (and moving everything into a single file).

The problem you have is due to improper transaction configuration. You have the how, the HibernateTransactionManager but not the when/where configured. I would expect a <tx:annotation-driven /> or <tx:advice /> with <aop:config /> to enable transactions.

I suggest a read of the transaction chapter in the Spring Reference Guide, for more information on hibernate read the hibernate section.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Thank you, it partially solved problems. I can make operations over entities using `getCurrentSession()`. But there is another problem, I think that it relates with multiple opened sessions. Look on the update please. – misco Dec 04 '13 at 09:13
  • That has to do with wrong transaction setup. Your service layer should be the transactional layer not the dao. So basically the method that does get/modify/update should be transactional. – M. Deinum Dec 04 '13 at 09:35
  • It is weird, because there is set on webapp context and every service that call dao methods have @Service annotation. – misco Dec 04 '13 at 10:38
  • Your advice was correct. I had transactions enabled, but there didn't work OSIV filter. I had to set it like interceptor - it fixed all issues. – misco Dec 05 '13 at 21:32
  • `@Service` has nothing to do with `@Transactional`. Instead of using the OSIVF or OSIVI simply annotate your service with `@Transactional` (as I mentioned in my previous comment). – M. Deinum Dec 06 '13 at 07:02