使用OpenSessionInView过滤器在hibernate中更新对象

时间:2014-01-07 18:35:01

标签: java hibernate java-ee spring-mvc open-session-in-view

我正在尝试更新hibernate中的对象,但我不明白为什么它没有在db中更新。有人可以帮忙吗?

控制器类

package com.petclinic.controller;
import com.petclinic.ClinicService;
import com.petclinic.Owner;

@Controller
@RequestMapping("/owners/{ownerId}/edit")
@SessionAttributes({"owner"})
public class EditOwnerForm {

    private final ClinicService clinicService;


    @Autowired
    public EditOwnerForm(ClinicService clinicService) {
        this.clinicService = clinicService;
    }

    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        dataBinder.setDisallowedFields("id");
    }

    //Mapping for GET Request
    @RequestMapping(method = RequestMethod.GET)
    public String setupForm(@PathVariable("ownerId") int ownerId, Model model) {
        Owner owner = this.clinicService.loadOwner(ownerId);
        model.addAttribute(owner);
        model.addAttribute("action", "editowner");
        return "owners/form";
    }

    //Mapping for POST Request
    @RequestMapping(method = RequestMethod.POST)
    public String processSubmit(@ModelAttribute Owner owner, /*BindingResult result,*/ SessionStatus status) {
        System.out.println(owner.toString());
        System.out.println("Inside EditOwner processSubmit method");
            this.clinicService.editOwner(owner);
            status.setComplete();
            return "redirect:/forms/owners/" + owner.getId();
    }
}

DAO课程

@Transactional
public void editOwner(Owner owner) {
        System.out.println("Inside editOwner method" + owner.getCity());
        sessionFactory.getCurrentSession().update(owner);
    }

我正在尝试更新所有者的城市,但我没有得到更新。 这是我在控制台中得到的。在editOwner方法中,我得到了所有者的城市,所以我相信这个值是正确传递的。这与该方法有关。我尝试使用update,merge,saveOrUpdate,但似乎没有任何工作。

    `Inside Welcome Controller
/forms
Delivering the owner search page
owner's name searched :
Hibernate: select owner0_.ID as ID0_, owner0_.FIRST_NAME as FIRST2_0_, owner0_.LAST_Name as LAST3_0_, owner0_.ADDRESS as ADDRESS0_, owner0_.CITY as CITY0_, owner0_.TELEPHONE as TELEPHONE0_ from OWNERS owner0_ where owner0_.LAST_Name like ?
FindOwner result from db [[Owner@3f305 id = 1, new = false, lastName = 'Franklin', firstName = 'George', address = '110 W. Liberty St.', city = 'Madison', telephone = '6085551023'], [Owner@1a5214b id = 2, new = false, lastName = 'Davis', firstName = 'Betty', address = '638 Cardinal Ave.', city = 'Sun Prairie', telephone = '6085551749'], [Owner@2ccaf3 id = 3, new = false, lastName = 'Rodriquez', firstName = 'Eduardo', address = '2693 Commerce St.', city = 'McFarland', telephone = '6085558763'], [Owner@c0290c id = 4, new = false, lastName = 'Davis', firstName = 'Harold', address = '563 Friendly St.', city = 'Windsor', telephone = '6085553198'], [Owner@1c6e8c1 id = 5, new = false, lastName = 'McTavish', firstName = 'Peter', address = '2387 S. Fair Way', city = 'Madison', telephone = '6085552765'], [Owner@1daee61 id = 6, new = false, lastName = 'Coleman', firstName = 'Jean', address = '105 N. Lake St.', city = 'Monona', telephone = '6085552654'], [Owner@58526a id = 7, new = false, lastName = 'Black', firstName = 'Jeff', address = '1450 Oak Blvd.', city = 'Monona', telephone = '6085555387'], [Owner@8ad65b id = 8, new = false, lastName = 'Escobito', firstName = 'Maria', address = '345 Maple St.', city = 'Madison', telephone = '6085557683'], [Owner@ff1cc0 id = 9, new = false, lastName = 'Schroeder', firstName = 'David', address = '2749 Blackhawk Trail', city = 'Madison', telephone = '6085559435'], [Owner@b89c6e id = 10, new = false, lastName = 'Estaban', firstName = 'Carlos', address = '2335 Independence La.', city = 'Waunakee', telephone = '6085555487'], [Owner@262743 id = 11, new = false, lastName = 'sarawagi', firstName = 'shivang', address = 'whitefield', city = 'bangalore', telephone = '12345'], [Owner@dbc09c id = 12, new = false, lastName = 'Hood', firstName = 'Robin', address = 'Atlanta', city = 'Newyork', telephone = '0989890829'], [Owner@142464f id = 13, new = false, lastName = 'Hearty', firstName = 'Hale', address = 'taiwan', city = 'Atlanta', telephone = '8967867868']]
Multiple Owners found
Returning owners/list
Hibernate: select owner0_.ID as ID0_0_, owner0_.FIRST_NAME as FIRST2_0_0_, owner0_.LAST_Name as LAST3_0_0_, owner0_.ADDRESS as ADDRESS0_0_, owner0_.CITY as CITY0_0_, owner0_.TELEPHONE as TELEPHONE0_0_ from OWNERS owner0_ where owner0_.ID=?
Hibernate: select owner0_.ID as ID0_0_, owner0_.FIRST_NAME as FIRST2_0_0_, owner0_.LAST_Name as LAST3_0_0_, owner0_.ADDRESS as ADDRESS0_0_, owner0_.CITY as CITY0_0_, owner0_.TELEPHONE as TELEPHONE0_0_ from OWNERS owner0_ where owner0_.ID=?
[Owner@1df63f9 id = 8, new = false, lastName = 'Escobito', firstName = 'Maria', address = '345 Maple St.', city = 'Mumbai', telephone = '6085557683']
Inside EditOwner processSubmit method
Inside editOwner method Mumbai
Hibernate: select owner0_.ID as ID0_0_, owner0_.FIRST_NAME as FIRST2_0_0_, owner0_.LAST_Name as LAST3_0_0_, owner0_.ADDRESS as ADDRESS0_0_, owner0_.CITY as CITY0_0_, owner0_.TELEPHONE as TELEPHONE0_0_ from OWNERS owner0_ where owner0_.ID=?
`

DAO类的代码

package com.petclinic.hibernate;

import java.util.Collection;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.petclinic.Clinic;
import com.petclinic.Owner;

 * <p>Note that transactions are declared with annotations and that some methods
 * contain "readOnly = true" which is an optimization that is particularly
 * valuable when using Hibernate (to suppress unnecessary flush attempts for
 * read-only operations).

@Repository
@Transactional
//HibernateClinic behaves as a DaoImpl/Repository class
public class HibernateClinic implements Clinic {


    private SessionFactory sessionFactory;

    @Autowired
    public HibernateClinic(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }


    @Transactional(readOnly = true)
    @SuppressWarnings("unchecked")
    public Collection<Owner> findOwners(String lastName) {
        return sessionFactory.getCurrentSession().createQuery("from Owner owner where owner.lastName like :lastName")
                .setString("lastName", lastName + "%").list();
    }

    @Transactional(readOnly = true)
    public Owner loadOwner(int id) {
        return (Owner) sessionFactory.getCurrentSession().load(Owner.class, id);
    }

    public void storeOwner(Owner owner) {
        //A transient object without an id will always be saved by hibernate's save() or persist() method
        sessionFactory.getCurrentSession().save(owner);
    }

    @Transactional
    public void editOwner(Owner owner) {
        //A transient object without an id will always be saved by hibernate's save() or persist() method
        System.out.println("Inside editOwner method" + owner.getCity());
        sessionFactory.getCurrentSession().update(owner);
    }

}

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd">

    <display-name>PetClinic</display-name>

    <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/applicationContext.xml
        </param-value>
        </context-param>

     <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>


    <servlet>
      <servlet-name>dispatcher</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>
      <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
      <servlet-name>dispatcher</servlet-name>
      <url-pattern>/forms/*</url-pattern>
    </servlet-mapping>

    <filter>
      <filter-name>hibernateFilter</filter-name>
      <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
      <init-param>
         <param-name>sessionFactoryBeanName</param-name>
         <param-value>sessionFactory</param-value>
      </init-param>
   </filter>

   <filter-mapping>
     <filter-name>hibernateFilter</filter-name>
     <url-pattern>/forms/*</url-pattern>
   </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>    
</web-app>

调度-servlet.xml中

<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <context:component-scan base-package="com.petclinic"/>

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
            p:basename="messages"/>

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">

        <property name="prefix">
            <value>/WEB-INF/view/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

</beans>

的applicationContext.xml

<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

     <context:annotation-config />

    <!-- <context:property-placeholder> XML element automatically registers a new PropertyPlaceholderConfigurer 
    bean in the Spring Context. -->
    <context:property-placeholder location="classpath:database.properties" />

    <!-- enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="hibernateTransactionManager"/> 

    <!-- Creating DataSource -->
      <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${database.driver}" />
        <property name="url" value="${database.url}" />
        <property name="username" value="${database.user}" />
        <property name="password" value="${database.password}" />
      </bean>

    <!-- To persist the object to database, the instance of SessionFactory interface is created. 
SessionFactory is a singleton instance which implements Factory design pattern. 
SessionFactory loads hibernate.cfg.xml and with the help of TransactionFactory and ConnectionProvider 
implements all the configuration settings on a database. -->

<!-- Configuring SessionFactory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="annotatedClasses">
            <list>
                <value>com.petclinic.Owner</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>             
            </props>
        </property>
    </bean>

<!-- Configuring Hibernate Transaction Manager -->
    <bean id="hibernateTransactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    </beans>

2 个答案:

答案 0 :(得分:0)

放置

<context:component-scan base-package="com.petclinic"/>

在applicationContext.xml中。

答案 1 :(得分:0)

我相信我发现了问题。我正在使用带有HibernateTransaction Manager的OpenSessionInView过滤器。默认情况下,此过滤器不会刷新Hibernate会话,刷新模式设置为FlushMode.NEVER。它假定与关注刷新的服务层事务结合使用:活动事务管理器将在读写事务期间临时将刷新模式更改为FlushMode.AUTO。我不知道为什么Hibernate事务管理器不会刷新会话。所以我在更新方法&amp;之后添加了getCurrentSession.flush()有效。有什么意见吗?

我甚至将OSIV Filter的FlushMode配置为commit / Auto&amp;检查,它没有工作,所以不得不求助于手动刷新会话。