简体   繁体   中英

spring mvc + hibernate: createSQLQuery is not valid without active transaction

The old version of my code:

    Session session = sessionFactory.openSession();
    Query query = session.createQuery("From User");
    List<Users> users = query.list();
    session.close();

I config the hibernate.cfg.xml file:

<property name="hibernate.current_session_context_class" > thread</property >

context.xml

<tx:annotation-driven transaction-manager="transactionManager"/>

Current code:

  Session session = sessionFactory.getCurrentSession();
  Transaction tx = session.beginTransaction();
  Query query = session.createQuery("From User");
  List<Users> list = query.list();
  tx.commit();

I have to add Transaction code, or I will get an error

org.hibernate.HibernateException: createQuery is not valid without active transaction

What am I missing for the config?

ApplicationContext.xml

<?xml version='1.0' encoding='UTF-8' ?>
  ......
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
    <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
</bean>
<context:annotation-config />
<context:component-scan base-package="*" />      
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"       class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>


public class IndexController {


@Autowired
UserService users;

@RequestMapping("/index")
public String index(ModelMap model ) {

 User user=   users.test();
 model.put("user", user);
    return "index";
}

As suggested @eg04lt3r you don't need this line in the hibernate.cfg.xml

<property name="hibernate.current_session_context_class">thread</property>

You need to configure your spring context properly.

For the session factory, if you have mapping and properties in hibernate.cfg.xml and hibernate.properties

<bean id="sessionFactory"  
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" />

for a transaction management

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="transactionManager"   
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

In a class that works with a session

public class Service {

    @Autowired
    private SessionFactory sessionFactory;

    @Transactional
    public List<User> list() {
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery("from User");
        return (List<User>) query.list();
    }

}

You can't get users by this way of course

new Service().list()

You need to get Service from the spring context. Spring will set sessionFactory in the Service and return a proxy for Service . When you call list() a proxy open a session and create a transaction.

Update

I reproduce your problem. With this classes everything works fine

public interface TextService {

    public void save();

    public List<SingleText> test();

}


@Service
public class TextServiceImpl implements TextService {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    @Transactional
    public void save() {
        SingleText text = new SingleText();
        text.setTestText("S.Grey");

        Session session = sessionFactory.getCurrentSession();
        session.save(text);
    }

    @Override
    @Transactional
    public List<SingleText> test() {
        Session session = sessionFactory.getCurrentSession();
        return session.createCriteria(SingleText.class).list();
    }

}

Without the @Transactional annotation I got

org.hibernate.HibernateException: No Session found for current thread

or (it depends of the Spring version)

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread

So you just need the @Transaction annotation. And you don't need this

<property name="hibernate.current_session_context_class">thread</property> 

Just remove this property if you do not use JTA. Spring do management transaction by default.

And define transaction manager in spring configuration:

<bean id = "transactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name = "sessionFactory" ref = "sessionFactory" />
</bean>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM