Frage

I have a Spring/JPA/Groovy/Hibernate stack, (note: not grails), and I'm finding that I'm getting a No session found for current thread when trying to perform some @Transactional work on startup.

I have a controller class that, upon @PostConstruct, invokes a @Transactional method on another class which tries to populate the database with some sample data to be used in a simulation.

Here's the controller class:

@Component
public class SimulationController {

    private TransactionTemplate transactionTemplate;
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
    private IPublisher publisher;

    @PostConstruct
    public void intialize()
    {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus arg0) {
                racePublisher.populateData();
            }
        });
    }
    //  Also tried, with no success:    
    //  @PostConstruct
    //  public void initialize()
    //  {
    //      publisher.populateData();
    //  }
}

As you can see, I've moved away from a pure @Transactional approach in the @PostConstruct for reasons discussed here.

My IPublisher is a groovy class, as follows:

@Component
class Publisher implements IPublisher {

@Autowired
IStockDAO stockDAO

void populateData()
{
    createStock()
}
@Transactional
void createStock()
{
    def list = [new Stock(ticker: "ADBE", name: "Adobe"),
                new Stock(ticker: "MSFT", venueCode: "Microsoft")]
    list.each { stockDAO.create it }
}

Which is an implementation of:

public interface IPublisher {

    public void populateData();
    public void createStock();
}

Note, I've also tried marking populateData() as @Transactional, with no effect.

In my Spring context class, I'm defining <tx:annotation-driven/>.

As far as I can tell, I've done everything correctly. However, I can't seem to get this to work.

What else is required?

Updated: Here are the beans setting up my dataAccess related beans:

<beans>
<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven/>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://${database.host}:${database.port}/${database.name}" />
        <property name="username" value="${database.username}" />
        <property name="password" value="${database.password}" />
        <property name="initialSize" value="5" />
        <property name="maxActive" value="50" />
    </bean>
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan">
            <list>
                <value>com.mangofactory.concorde</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider
                </prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop><!--  use create for full drop/create -->
                <prop key="hibernate.connection.autocommit">true</prop>
                <prop key="hibernate.statement_cache.size">0</prop>
                <prop key="hibernate.jdbc.batch_size">20</prop>
            </props>
        </property>
    </bean>
    <beans>
War es hilfreich?

Lösung

You should use HibernateTransactionManager instead of DataSourceTransactionManager.

Andere Tipps

There are basic issues with the code. The transactional boundary starts in the createStock method of the Publisher class and ends there. It does not propagate to your controller . Use the DB query calls inside a transaction . i.e , inside a method which has the Transactional annotation. Else it would never work .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top