Spring 3 + Hibernate: java.sql.BatchUpdateException: невозможно добавить или обновить дочернюю строку (ManyToMany) - PullRequest
1 голос
/ 22 июня 2011

У меня проблема с сохранением элемента учетной записи после редактирования.Элемент Account содержит набор ролей (@ManyToMany).Если я загружаю элемент «Аккаунт» и пытаюсь его отредактировать, все работает нормально, пока я не попытаюсь добавить новые роли.Роли представлены флажками.Те, которые изначально проверены, также проверяются в форме редактирования.Если я сейчас попытаюсь проверить и некоторые другие и сохранить измененную учетную запись, я получу исключение из Hibernate:

java.sql.BatchUpdateException: Невозможно добавить или обновить дочернюю строку: aСбой ограничения внешнего ключа (fi_mc-tool. account_role, CONSTRAINT FK4AC9CB881F90989D FOREIGN KEY (Account_id) ССЫЛКИ Account (id))

В роли объекта у меня нетопределены любые отношения к Аккаунту.Это только что определено в учетной записи.Может ли это быть причиной?

Выписка из учетной записи:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
@JoinTable(name = "Account_Role", joinColumns = { 
    @JoinColumn(name = "Account_id") }, 
    inverseJoinColumns = { @JoinColumn(name = "Role_id") })
private Set<Role> roles = new HashSet<Role>(0);

Выписка из службы учета:

@Transactional
public void merge(Account account) {
    accountDAO.merge(account);
}

Извлечениесчета DAO:

public void merge(Account account) {
    sessionFactory.getCurrentSession().merge(account);
}

Выписка из edit.jsp учетной записи

    <tr>
        <td style="width:75px">
            <label for="roles"><spring:message code="labels.account.form.roles" text="Roles" /></label>
        </td>
        <td>
            <form:checkboxes path="roles" items="${roleList}" itemLabel="name" itemValue="idAsString" delimiter="<br/>"/> 
        </td>

</tr>

Выписка из контроллера учетной записи

/**
 * edit() - Save edited item
 * @param id of changed object
 * @param item which has been changed
 * @return  path to view
 */
@RequestMapping(value="/edit/{id}", method=RequestMethod.POST)
public String edit(@PathVariable("id") Long id, @ModelAttribute("item") Account item, BindingResult bindingResult, Model model) {
    accountService.merge(item);

    return "redirect:/account/list";
}

/**
 * edit() - Edit an item
 * @param id of item to change
 * @param model to store item
 * @return  path to view
 */
@RequestMapping(value="/edit/{id}", method=RequestMethod.GET)
public String editForm(@PathVariable("id") Long id, Model model) {
    Account item = accountService.load(id);

    for(Role r : item.getRoles()){
        System.out.println("ROLE ITEM: ID="+r.getId()+" | NAME="+r.getName()+" | HASH="+r);
    }

    for(Role r : roleService.list()){
        System.out.println("ROLE SERVICE: ID="+r.getId()+" | NAME="+r.getName()+" | HASH="+r);
    }

    model.addAttribute("item", item);
    model.addAttribute("roleList", roleService.list());

    return "account/edit";
}

Извлечение из spring-servlet.xml:

<!-- Activates various annotations to be detected in bean classes -->
<context:annotation-config />

<!-- Scans the classpath for annotated components that will be auto-registered as Spring beans -->
<context:component-scan base-package="fi.java.elearning.*" />

<!-- Configures the annotation-driven Spring MVC Controller programming model -->
<mvc:annotation-driven /> 

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />

<!-- Include Tiles for View Rendering -->
<bean id="viewResolver"
    class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass">
        <value>
            org.springframework.web.servlet.view.tiles2.TilesView
        </value>
    </property>
</bean>

<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
    <property name="definitions">
        <list>
            <value>/WEB-INF/configurations/tiles/tiles.xml</value>
        </list>
    </property>
</bean>

<!-- multipart file resolver bean -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>   


<!-- multi language support -->

<bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
    <property name="defaultLocale" value="de" />
</bean>

<bean id="localeChangeInterceptor"
    class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="language" />
</bean>

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
    <property name="interceptors">
       <list>
        <ref bean="localeChangeInterceptor" />
       </list>
    </property>
</bean>

<bean id="messageSource"
    class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="languages/messages" />
</bean>

<!-- Import Hibernate Context -->
<import resource="configurations/hibernate/hibernate-context.xml" />

<!-- Import Spring Security -->
<import resource="configurations/spring/spring-security.xml" />

Извлечение из web.xml:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring-servlet.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>
<servlet>
  <servlet-name>spring</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>spring</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>
<error-page>
  <error-code>404</error-code>
  <location>/WEB-INF/views/contents/exceptions/404.jsp</location>
</error-page>

Извлечение из hibernate.context.xml:

<context:property-placeholder location="/WEB-INF/configurations/hibernate/database.properties" />

<!-- Declare the Hibernate SessionFactory for retrieving Hibernate sessions -->
<!-- See http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.html -->                           
<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/SessionFactory.html -->
<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/Session.html -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
             p:dataSource-ref="dataSource"
             p:configLocation="${hibernate.config}"
             p:packagesToScan="fi.java.elearning"/>

<!-- Declare a datasource that has pooling capabilities-->   
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
            destroy-method="close"
            p:driverClass="${app.jdbc.driverClassName}"
            p:jdbcUrl="${app.jdbc.url}"
            p:user="${app.jdbc.username}"
            p:password="${app.jdbc.password}"
            p:acquireIncrement="5"
            p:idleConnectionTestPeriod="60"
            p:maxPoolSize="100"
            p:maxStatements="50"
            p:minPoolSize="10" />

<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" 
            p:sessionFactory-ref="sessionFactory" />

<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />   

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...