oddly
oddly

Reputation: 260

save is not valid without active transaction - hibernate&spring

First of all, I have searched other similar questions here before.Though, I couldn't figure out where I have mistaken.

In Eclipse, I have been building a simple Hibernate+Spring+MySQL+Maven project recently.I am having trouble at the stage of database&java connection.When I run the project, it gives the the following error:

WARN : org.hibernate.internal.util.xml.DTDEntityResolver - HHH000223:Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
WARN : org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator - HHH000181: No appropriate connection provider encountered, assuming application will be supplying connections
Transaction began Exception in thread "main" org.hibernate.HibernateException: save is not valid without active transaction
at   org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
at com.sun.proxy.$Proxy19.save(Unknown Source)
at com.test.Main.main(Main.java:33)

The main class:

package com.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

import com.hibernate.data.Person;

public class Main {
public static void main(String [] args){

// Create a configuration instance
Configuration configuration = new Configuration();
// Provide configuration file
configuration.configure("hibernate.cfg.xml");
// Build a SessionFactory
SessionFactory factory = configuration.buildSessionFactory(new StandardServiceRegistryBuilder().configure().build());
// Get current session, current session is already associated with Thread
Session session = factory.getCurrentSession();
// Begin transaction, if you would like save your instances, your calling of save must be associated with a transaction
Transaction tx = session.getTransaction();

// Create person
Person newPerson = new Person();
newPerson.setFirstName("Peter");
newPerson.setLastName("Jackson");
newPerson.setGender("Male");
newPerson.setAge(30);
//Save
session.save(newPerson);
session.flush();

tx.commit();
session.close();
}
}

hbm.xml file:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
      "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class table="Person" lazy="false" name="com.hibernate.data.Person" >
    <id column="PERSON_ID" type="int" name="id" >
        <generator class="increment"/>
    </id>
        <property name="firstName" column="PERSON_FIRSTNAME" type="string" />
        <property name="lastName" column="PERSON_LASTNAME" type="string" />
        <property name="gender" column="PERSON_GENDER" type="string" />
        <property name="age" column="PERSON_AGE" type="int"  />
  </class>
</hibernate-mapping>

hibernate.cfg.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>
<!-- Database connection settings -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/PERSONDB</property>
<property name='connection.username'>root</property>
<property name='connection.password'>root</property>

<!-- SQL dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Specify session context -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- Show SQL -->
<property name="show_sql">true</property>
<!-- Referring Mapping File -->
<mapping resource="domain-classes.hbm.xml"/>
<mapping class="com.hibernate.data.Person"/>
</session-factory>

</hibernate-configuration>

applicationContext.xml file:

<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- Enable Spring Annotation Configuration -->
<context:annotation-config />
<!-- Scan for all of Spring components such as Spring Service -->
<context:component-scan base-package="com.spring.service"></context:component-scan>
<!-- Create Data Source bean -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/PERSONDB" />
    <property name="username" value="root" />
    <property name="password" value="root" />
</bean>
<!-- Define SessionFactory bean -->
<bean id="sessionFactory"
       class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mappingResources">
        <list>
            <value>domain-classes.hbm.xml</value>
        </list>
    </property>
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
</bean>
<!-- Transaction Manager -->
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Detect @Transactional Annotation -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

How can I fix this?

Upvotes: 1

Views: 1679

Answers (1)

JB Nizet
JB Nizet

Reputation: 691635

You forgot to begin the transaction:

Transaction tx = session.getTransaction();
tx.begin();

or, easier:

Transaction tx = session.beginTransaction();

Note that your problem is unrelated to Spring, since you're not using Spring at all in the posted code. When you do, you'll have to fix your Spring configuration: don't use classes from the hibernate3 package, since you're using hibernate4. Also, learn to use annotations and not hbm.xml files to map your entities. XML was useful in Java 1.4. But we're noaw at Java 1.8.

Upvotes: 1

Related Questions