Spring数据JPA和hibernate分离实体传递给ManyToMany关系持久化 [英] Spring data JPA and hibernate detached entity passed to persist on ManyToMany relationship

查看:32
本文介绍了Spring数据JPA和hibernate分离实体传递给ManyToMany关系持久化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试持久化一个与其他已持久化对象具有多对多关系的对象.

I am trying to persist an object that has a many-to-many relationship with other objects already persisted.

这是我的持久化对象(它们已经持久化在数据库中,它是一个 MySql):-

Here is my persisted object (they are already persisted in the db, which is a MySql):-

产品

@Entity
@Table(name="PRODUCT")
public class Product {
    private int productId;
    private String productName;
    private Set<Reservation> reservations = new HashSet<Reservation>(0);

    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    public int getProductId() {
        return productId;
    }

    public void setProductId(int productId) {
        this.productId = productId;
    }

@Column(nullable = false)
    public String getProduct() {
        return product;
    }
    public void setProduct(String product) {
        this.product = product;
    }

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "products")
    public Set<Reservation> getReservations() {
        return reservations;
    }
    public void setReservations(Set<Reservation> reservations) {
        this.reservations = reservations;
    }
}

这是我正在尝试创建的非持久对象

Here is my no persisted object, which I am trying to create

@Entity
@Table(name = "RESERVATION")
public class Reservation {

    private int reservationId;

    private Set<Product> products = new HashSet<Product>(0);

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getReservationId() {
        return reservationId;
    }

    public void setReservationId(int reservationId) {
        this.reservationId = reservationId;
    }

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name = "product_reservation", joinColumns = { @JoinColumn(name = "reservationId", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "productId", 
            nullable = false, updatable = false) })
    public Set<Product> getProducts() {
        return products;
    }

    public void setProducts(Set<Product> products) {
        this.products = products;
    }
}

这是我的 ReservationService 类,它接收一组产品名称,使用名称查找产品并将它们放入预订对象中.

This is my ReservationService class, which receives an array of products names, look the products using the name and put them into the reservation object.

@Service
public class ReservationServiceImpl implements ReservationService {

    @Autowired
    private ProductDAO productDAO;
    @Autowired
    private ReservationDAO reservationDAO;

    @Transactional
    public void createReservation(String[] productNames) {

            Set<Product> products = new HashSet<Product>();
            for (String productName : productNames) {
                Product pi = productDAO.findByProductName(productName);
                products.add(pi);
            }
            Reservation reservation = new Reservation();
            reservation.setProducts(products);
            reservationDAO.save(reservation);   ---> Here I am getting detached entity passed to persist
    }
}

这是我的 ProductDAO 接口:

public interface ProductDAO extends JpaRepository<Product, Integer> {

    public Product findByProductName(String productName);
}

这是我的 spring 配置文件:

This is my spring config file:

@Configuration
@PropertySource(value = { "classpath:base.properties" })
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.reservation.dao")
public class RepositoryConfig {

    @Autowired
    private Environment env;

    @Bean
    public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        EntityManagerFactory factory = entityManagerFactory().getObject();
        return new JpaTransactionManager(factory);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(Boolean.valueOf(env
                .getProperty("hibernate.generate.ddl")));
        vendorAdapter.setShowSql(Boolean.valueOf(env
                .getProperty("hibernate.show_sql")));

        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.hbm2ddl.auto",
                env.getProperty("hibernate.hbm2ddl.auto"));
        jpaProperties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(dataSource());
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan("com.reservation.service.domain");
        factory.setJpaProperties(jpaProperties);
        factory.afterPropertiesSet();
        factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
        return factory;
    }

    @Bean
    public HibernateExceptionTranslator hibernateExceptionTranslator() {
        return new HibernateExceptionTranslator();
    }

    @Bean
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        return dataSource;
    }
}

这是完整的堆栈跟踪:

严重:servlet [dispatcher] 的 Servlet.service() 在路径为 [/web] 的上下文中抛出异常 [请求处理失败;嵌套异常是 org.springframework.dao.InvalidDataAccessApiUsageException: 分离实体传递给持久化:com.reservation.service.domain.Product;嵌套异常是 org.hibernate.PersistentObjectException: 分离实体传递给持久性:com.reservation.service.domain.Product] 与根本原因org.hibernate.PersistentObjectException:分离的实体传递给持久化:com.reservation.service.domain.Product在 org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/web] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.reservation.service.domain.Product; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.reservation.service.domain.Product] with root cause org.hibernate.PersistentObjectException: detached entity passed to persist: com.reservation.service.domain.Product at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)

推荐答案

我遇到了同样的问题,并通过删除 cascade = CascadeType.PERSIST 解决了它.

I had the same problem and solved it by removing the cascade = CascadeType.PERSIST.

根据文档,在您的情况下,您使用 CascadeType.ALL,这相当于也使用 PERSIST:

In your case you use CascadeType.ALL, which is equivalent to also using the PERSIST, according to the documentation:

定义传播到关联实体的可级联操作集.值cascade=ALL 等价于cascade={PERSIST, MERGE, REMOVE, REFRESH, DETACH}.

Defines the set of cascadable operations that are propagated to the associated entity. The value cascade=ALL is equivalent to cascade={PERSIST, MERGE, REMOVE, REFRESH, DETACH}.

这意味着当您尝试在 reservationDAO.save(reservation) 上保存预订时,它也会尝试持久化关联的 Product 对象.但是这个对象没有附加到这个会话中.所以错误发生了.

It means when you try to save the reservation on reservationDAO.save(reservation) it will also try to persist the associated Product object. But this object is not attached to this session. So the error occur.

这篇关于Spring数据JPA和hibernate分离实体传递给ManyToMany关系持久化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆