@Transactional 不会在数据库中生成 INSERT

@Transactional doesn't genetate INSERT in database

我正在使用 Spring+Hibernate 提供 REST 服务并尝试调整事务。 当我保存在带有注释的@Transactional 函数中时,Hibernate 不会使用 entitiy INSERT 语句生成查询。仅接收新 ID。这是日志:

Hibernate: select next_val as id_val from hibernate_sequence for update
Hibernate: update hibernate_sequence set next_val= ? where next_val=? 

我的源文件:

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation=
            "http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx-4.3.xsd 
            http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-4.3.xsd 
            ">

    <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost/project8098" />
      <property name="username" value="usr" />
      <property name="password" value="pwd" />
   </bean>  

  <bean id="sessionFactory"
    class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
      <property name="dataSource" ref="dataSource" />
      <property name="packagesToScan" value="cama.entities" />
      <property name="hibernateProperties">
         <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> 
            <prop key="hibernate.show_sql">true</prop>
         </props>
      </property>
   </bean>  

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

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

    <context:annotation-config/>
    <context:component-scan base-package="cama.controllers"/>
    <context:component-scan base-package="cama.dao"/> 
    <context:component-scan base-package="cama.dao.users" />   
    <context:component-scan base-package="cama.messages.email"/>
    <context:component-scan base-package="cama.messages.firebase"/> 

    ...

</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Children Attendance Monitoring Application</display-name>


  <servlet>
      <servlet-name>cama</servlet-name>
          <servlet-class>
              org.springframework.web.servlet.DispatcherServlet
          </servlet-class>
      <load-on-startup>1</load-on-startup>
  </servlet>
   <listener>
       <listener-class>
           org.springframework.web.context.ContextLoaderListener
       </listener-class>
   </listener> 
    <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>
           /WEB-INF/beans.xml
           /WEB-INF/security.xml
           /WEB-INF/test.xml
       </param-value>
    </context-param> 
    <servlet-mapping>
        <servlet-name>cama</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>
            org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <session-config>
        <session-timeout>0</session-timeout>
    </session-config>

</web-app>

cama-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc 
                        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
                        http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-4.3.xsd                        
                        ">


   <context:component-scan base-package="cama.controllers"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/jsp/" />
      <property name="suffix" value=".jsp" />
    </bean> 

    <mvc:view-controller path="/" view-name="index"/>

   <mvc:annotation-driven/> 

   <!-- Configure to plugin JSON as request and response in method handler -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonMessageConverter"/>
            </list>
        </property>
    </bean>

    <bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>

</beans>

Class 带控制器

package cama.controllers;

import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import cama.dao.users.AdministratorDAO;
import cama.entities.Administrator;
import cama.resources.URL;

@RestController
@RequestMapping(URL.ADMINISTRATORS)

public class AdministratorController extends AbstractController{

    @Autowired
    private AdministratorDAO controllerDAO;


    @RequestMapping(method=RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    public @ResponseBody Administrator create(@RequestBody Administrator entity){       

        controllerDAO.save(entity);

        return entity;

    }

    ....

}

DAO class:

package cama.dao.users;


import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import cama.entities.User;

public abstract class AdministratorDAO{


    @Transactional
    public void save(Administrator entity) {
        Session session = getSessionFactory().openSession();    
        entity.setNewSecretCode();
        session.save(entity);
        //session.flush(); //Without flush doesn't save entity !!!
        session.close();
    }


    ...


}

请帮我看看哪里出了问题。当我执行删除操作时,它可以正常工作并删除实体。

Afaik,如果您使用 @Transactional 注释,则不必手动打开和关闭会话。所以,在你的道中:

@Transactional
public void save(Administrator entity) {
   Session session = getSessionFactory().getCurrentSession();
   entity.setNewSecretCode();
   session.save(entity);
}

它将是负责打开事务、刷新会话和提交事务的容器,将实体保存在您的数据库中。

当使用 @Transactional 时,Hibernate 对数据库的写入是在您调用 flush() 之前不会提交的事务中。这在您可能想要回滚事务时很有用。