1

Spring MVC 3 と OpenSessionInViewFilter を使用して、アプリケーションで休止状態からオブジェクトを更新しようとして約 5 時間かかりましたが、運がありませんでした。

StackOverflow やその他のフォーラムで利用可能なすべてのスレッドを調べた可能性があります。

Hibernate はエラーをスローせず、オブジェクトが更新されたと言いますが、DB には反映されません。

どんな助けでも大歓迎です。

したがって、更新するJSON 要求は次のとおりです。

{
    "id": "14",
    "name": "Whatever",
    "contactNumber": "918026754027",
    "manager": "Vishwas", --> I've updated this value
    "capacity": "222",
    "addressId": "31",
    "streetAddress": "1168, 1st Block, 17th Main, ABC",
    "countryId": "1",
    "stateId": "1",
    "cityId": "1",
    "area": "DEF",
    "pincode": "560050"
}

コントローラ:

@RequestMapping(value = "/branches/update", method = RequestMethod.POST, headers = {"Content-Type=application/json"})
    @ResponseBody
    public Map<String, Object> updateBranch(@RequestBody Map<String, String> requestMap) {
        boolean status = false;
        boolean branchStatus = false;
        Map<String, Object> statusMap = new HashMap<String, Object>();
        Branch branch = new Branch();

        Address address = new Address();
        address.setId(Long.parseLong(requestMap.get("addressId")));        
        address.setCountry(countryService.getCountryById(Long.parseLong(requestMap.get("countryId"))));
        address.setState(stateService.getStateById(Long.parseLong(requestMap.get("stateId"))));
        address.setCity(cityService.getCityById(Long.parseLong(requestMap.get("cityId"))));
        address.setType("BRANCH");
        address.setArea(requestMap.get("area"));
        address.setStreetAddress(requestMap.get("streetAddress"));
        address.setPincode(requestMap.get("pincode"));
        address.setModifiedBy("vishwas");
        address.setModifiedTimestamp(new Date());

        status = addressService.updateAddress(address);

        if (status) {
            branch.setId(Long.parseLong(requestMap.get("id")));
            branch.setName(requestMap.get("name"));
            branch.setAddress(address);
            branch.setContactNumber(requestMap.get("contactNumber"));
            branch.setManager(requestMap.get("manager"));
            branch.setActive(true);
            branch.setCapacity(Integer.parseInt(requestMap.get("capacity")));
            branch.setModifiedTimestamp(new Date());
            branch.setModifiedBy("vishwas");            
            branchStatus = branchService.updateBranch(branch);
        }

        if (branchStatus) {
            statusMap.put("status", branchStatus);
            statusMap.put("message", "Branch was updated successfully");
        } else {
            boolean delStatus = addressService.deleteAddress(address);
            statusMap.put("status", branchStatus);
            statusMap.put("message", "Problem updating branch. Please check with your system administrator");
        }
        return statusMap;
    }

サービス クラス:

@Service("branchService")
@Transactional
public class BranchServiceImpl implements BranchService {

    @Autowired
    private BranchDAO branchDAO;
    private static Logger logger = Logger.getLogger(BranchService.class.getName());

    public boolean updateBranch(Branch branch) {
        logger.debug("Processing request to dao to update a branch --> " + branch.getId());
        return branchDAO.updateBranch(branch);
    }
}

DAO メソッド:

public boolean updateBranch(Branch branch) {
        boolean status = false;
        try {
            logger.debug("Trying to update a branch --> " + branch.getId());                            
            sessionFactory.getCurrentSession().update(branch);            
            status = true;
        } catch (HibernateException exception) {
            logger.error("Problem updating a branch --> " + exception.getMessage());
        } catch (Exception exception) {
            logger.error("Problem updating a branch --> " + exception.getMessage());
        }
        return status;
    }

**更新 2: Deinum 氏の提案に従って、トランザクション マネージャーの構成を o2-data.xml に移動し、o2-data.xml 内の他のコンポーネントをスキャンしながら、ディスパッチャー内のコントローラーのみをスキャンするようになりました。

データ構成

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

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.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
">
    <context:component-scan base-package="com.adwitiya.o2plus">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${database.driverClass}"/>
        <property name="url" value="${database.url}"/>
        <property name="username" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
    </bean>

    <!-- Hibernate Session Factory -->
    <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="packagesToScan">
            <array>
                <value>com.adwitiya.o2plus.model</value>
            </array>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQLDialect
                hibernate.show_sql=true
            </value>
        </property>
    </bean>

    <!-- Hibernate Transaction Manager -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

    <!-- Activates annotation based transaction management -->
    <tx:annotation-driven transaction-manager="transactionManager"/>


</beans>

ディスパッチャ構成:

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

    <context:component-scan base-package="com.adwitiya.o2plus">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <mvc:annotation-driven>
        <mvc:message-converters>
            <!-- Use the HibernateAware mapper instead of the default -->
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.adwitiya.o2plus.utilities.HibernateAwareObjectMapper"/>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

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

    <mvc:resources mapping="/gui/**" location="/gui/"/>

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:application.properties</value>
            </list>
        </property>
    </bean>

</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"
         version="3.0">

    <display-name>O2 Plus</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/o2-data.xml
            /WEB-INF/spring/o2-utils.xml
            /WEB-INF/spring/o2-security.xml
        </param-value>
    </context-param>

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

    <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>

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

    <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

    <servlet>
        <servlet-name>o2-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/o2-dispatcher-servlet.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>o2-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
4

3 に答える 3

2
<context:component-scan base-package="com.adwitiya.o2plus" />

これ<context:component-scan ... /> は、 によってロードされる設定にありますDispatcherServlet

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

<tx:annotation-driven />、 によってロードされる設定内にありますContextLoaderLIstener

Aは、ロードされているBean(Factory)PostProcessorのと同じ Bean に対してのみ動作しApplicationContextます。親コンテキストまたは子コンテキストの Bean に対しては何もしません。は、である<tx:annotation-driven />によって処理されるインターセプター (またはアスペクト) を登録します。InfrastructureAdvisorAutoProxyCreatorBeanPostProcessor

解決

<tx:annotation-driven />の構成に移動するかDispatcherServlet、コンポーネント スキャンを変更します。は注釈付き BeanContextLoaderListener以外をスキャンする必要がありますが、 は注釈付き Beanのみをスキャンする必要があります。@ControllerDispatcherServlet@Controller

ContextLoaderListener構成。

<context:component-scan base-package="com.adwitiya.o2plus">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> 
</context:component-scan>

DispatcherServlet構成

<context:component-scan base-package="com.adwitiya.o2plus" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> 
</context:component-scan>
于 2014-06-02T10:05:20.203 に答える
0

あなたが持っていることを確認してください:

@EnableTransactionManagement

およびセッション ファクトリを認識している Hibernate トランザクション マネージャ:

@Bean
public HibernateTransactionManager transactionManager() {           HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory().getObject());
    return transactionManager;
}

また

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

xml 構成を使用する場合。

フォールト Spring プロキシベースのトランザクション インターセプトを使用している限り、サービス レイヤーを簡単にデバッグしTransactionInterceptor、コントローラー呼び出しと実際のサービス メソッドの間の現在のスタック トレースを確認できます。

トランザクションがある場合は、TransactionInterceptorトランザクションを使用する必要があり、Hibernate トランザクションはインターセプターによって呼び出されます。

そして、新しいオブジェクトに対して Session.update を呼び出しています。Merge は、一時的なインスタンス、デタッチされたインスタンス、および既にアタッチされているインスタンスの両方で機能するため、優先されます。

したがって、代わりに:

sessionFactory.getCurrentSession().update(branch); 

あなたが持っている必要があります:

sessionFactory.getCurrentSession().merge(branch); 
于 2014-05-30T05:21:33.717 に答える