0

I am facing a problem that when I use hibernate+spring+mysql to commiting my data from pages to database,the transaction didn't commit. Or perhaps my configuration is somewhere wrong.

The following is my configuration and code:

1.spring-config.xml(The configuration of spring)

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/webtest?charset=UTF-8" />
        <property name="user" value="root" />
        <property name="password" value="kevin" />
        <property name="initialPoolSize" value="5"/>
        <property name="minPoolSize" value="5"/>
        <property name="maxPoolSize" value="15" />
        <property name="checkoutTimeout" value="1000" />
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.kevin" />
        <property name="namingStrategy">
            <bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="hibernate.hbm2ddl.auto">select</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
                <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                <!-- <prop key="connection.autocommit">true</prop> -->
            </props>
        </property>
    </bean>

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

    <tx:annotation-driven />
</bean>

2.User.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 *
 *@author kevin
 *@date 2015年5月29日 上午11:24:17
 *
 **/
@Entity
@Table(name="sys_user")
public class User implements Serializable{

    private static final long serialVersionUID = -8693332653054586507L;
    @Id
    @Column(name="user_id")
    private String id;
    @Column(name="user_real_name")
    private String name;
    @Column(name="user_education")
    private String edu;
    getter()setter()...
}

3.UserService.java

@Service
public class UserService {

    @Resource
    private UserDao userDao;

    @org.springframework.transaction.annotation.Transactional
    public boolean createUser(User user) {
        try {
            user.setId(String.valueOf(new Date().getTime()));
            userDao.add(user);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}

4.UserDao.java

@Repository
public class UserDao extends BaseDao<User, String>{
    public UserDao() {
        super(User.class);
    }
}

5.BaseDao.java

public abstract class BaseDao<T, PK extends Serializable> {
    private SessionFactory sessionFactory;
    private Class<T> cls;

    public BaseDao(Class<T> t) {
        cls = t;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    @Resource
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    //@Transactional
    public void add(T t) throws Exception {
        sessionFactory.getCurrentSession().save(t);
        //sessionFactory.getCurrentSession().flush();
    }
}

The code above is just a test code, but it cannot persist to the database. Of course, if I use session.flush(),it can commit to the database,but I think it is not a good way, because it cannot ensure the consistent of the transaction.

So I am puzzling heavy what wrong with my test and code.

cнŝdk
  • 31,391
  • 7
  • 56
  • 78
  • the engin of my mysql is InnoDB – user3839014 May 29 '15 at 09:23
  • Please, make the post minimal to make it more readable. Also, check the updated title and fix it to exactly summarize your question. – vefthym May 29 '15 at 09:27
  • [how to ask questions](https://stackoverflow.com/help/how-to-ask), [how to post code](https://stackoverflow.com/help/mcve) – specializt May 29 '15 at 09:28
  • You need to annotate your methods with @Transactional. – Stefan May 29 '15 at 09:28
  • Just to make things crystal clear: What is the observed behaviour? Do you get some sort of error message or exception, or do you just expect rows in a database when there are none? – Buhb May 29 '15 at 09:28
  • What did you get in your database? do you get empty tables? – cнŝdk May 29 '15 at 09:29
  • define the transaction manager use this `` instead of `` – RSCode May 29 '15 at 09:37
  • sorry for bothering you.I am new here and my english is poor,so sometimes i don't know how to organize my sentences..... – user3839014 May 29 '15 at 09:38
  • You will need to post the code of the class where you create and call the service i.e. your test class. You can remove the DAO classes from your question. Also flush != commit: you can safely flush without breaking the integrity of the transaction. – Alan Hay May 29 '15 at 09:39
  • Can you please let us know, which version of Hibernate you are using? – Arpit Aggarwal May 29 '15 at 09:40
  • @Robin Saxena...my project just have a datasource,so doesn't it just has one default transactionManager???I want to explain it that if i don't add the transaction-manager="transactionManager" proxy-target-class="true"...it doesn't use the default transactionManager?thanks....i will try it – user3839014 May 29 '15 at 09:45
  • @Arpit,yes,thanks ,the version of my hibernate is 4.3.7 – user3839014 May 29 '15 at 09:46
  • actually,when i excute my add method ,it didn't show me any error messages,it just didn't commit the transaction.......
    – user3839014 May 29 '15 at 09:49
  • There is probably nothing wrong with your code. You issue is likely one of mis-understanding. You need to post your test class and explain why it doesn't work. – Alan Hay May 29 '15 at 09:49
  • @Alan Hay...I have post my test method (in the controller) as a anwser of my own question,thanks for helping checking it.... – user3839014 May 29 '15 at 10:02

4 Answers4

0

Try changing the Transaction configuration in your spring-config.xml file:

<!-- Enable Annotation based Declarative Transaction Management -->
    <tx:annotation-driven proxy-target-class="true"
        transaction-manager="transactionManager" />
Arpit Aggarwal
  • 27,626
  • 16
  • 90
  • 108
0

define the transaction manager use this <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> instead of <tx:annotation-driven/> it will work fine for you.

RSCode
  • 1,573
  • 2
  • 13
  • 21
  • it enable the proxy class for transaction manager and `` is completely fine till spring 3 but spring 4 need to change it. – RSCode May 29 '15 at 09:43
  • Well you should explain that in your answer and provide some links to back it up. – Alan Hay May 29 '15 at 09:46
0

Here is my @controller, thanks all...

@RequestMapping(value = "/user/edit")
public String edit(User user) {
    if (user != null) {
        if (StringUtils.isNotBlank(user.getId())) {
            System.out.println(userService.editUser(user));
        } else {
            System.out.println(userService.createUser(user));
        }
    }
    return "";
}
Parkash Kumar
  • 4,710
  • 3
  • 23
  • 39
  • `@RequestMapping(value = "/user/edit", method = RequestMethod.POST, headers = "Accept=application/xml, application/json")` define the method type as POST,GET,DELETE,UPDATE and headers value as well – RSCode May 29 '15 at 10:12
  • use `@Autowired` instead of `@Resource` in the Service layer .. [http://stackoverflow.com/questions/20450902/inject-and-resource-and-autowired-annotations] please check the link as well. – RSCode May 29 '15 at 10:23
0

Of course, if I use session.flush(),it can commit to the database,but I think it is not a good way, because it cannot ensure the consistent of the transaction.

The fact that you state everything works if you call flush() is strange as flush() != commit().

By calling flush() all you are doing is asking the JPA provider to write any pending updates to the database right now rather when the transaction commits. While there may be cases where it is necessary to make an explicit call to flush(), normally you do not need to as the JPA provider will flush any pending updates just before trying to commit the transaction. The key point to note is that even after calling flush your updates will not be visible to another transaction until commit and calling flush does not break the integrity of your transaction.

So as I noted above, your code is most likely fine but your issue is one of mis-understanding.

Alan Hay
  • 22,665
  • 4
  • 56
  • 110