【问题标题】:ConstraintViolationException while saving entity with @OrderColumn and @OneToMany使用 @OrderColumn 和 @OneToMany 保存实体时出现 ConstraintViolationException
【发布时间】:2014-06-11 12:48:47
【问题描述】:

我有以下实体。

@Entity
public class Shop {
    @OneToMany( cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE }, orphanRemoval = true )
    @JoinTable( name = "shop_image",
            joinColumns = @JoinColumn( name = "shop_id" ),
            inverseJoinColumns = @JoinColumn( name = "image_id" ) )
    @OrderColumn( name = "order_number" )
    @BatchSize( size = 20 )
    private List<Image> images = new ArrayList<Image>( 0 );
}

shop_image 表 == (id PK, shop_id, image_id, order_number) 并具有唯一约束 (shop_id, image_id)。

当以下代码被调用时(在事务上下文中):

@PersistenceContext
EntityManager em;

@Transactional
// shop exist in DB
public void reorderImages(Shop shop) {
    //shop.getImages().size == 2; {img0, img1}
    List<Image> newImages = new ArrayList<>();
    newImages.add(shop.getImages().get(1));
    newImages.add(shop.getImages().get(0));
    shop.setImages(newImages); // {img1, img0}

    em.merge(shop);
}

我得到以下异常

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '5458-98711' for key 'uniqShopAndImage'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2427)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2345)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2330)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:187)
    ... 76 more

我知道可以:

  1. 从商店中删除所有图片 //shop.getImages().clear()
  2. em.flush()
  3. shop.setImages(newImages);
  4. em.merge(shop)

但我不喜欢这种解决方案。 我使用休眠 4 作为 JPA 提供程序,MySQL DB。 感谢您的回答。

【问题讨论】:

    标签: java spring hibernate jpa spring-transactions


    【解决方案1】:

    这个问题是因为 MySQL 不支持可延迟约束检查(意味着在提交 DB 事务时检查约束,而不是在执行单个 SQL 语句时)。详细答案是here

    关于我的问题,可以用

    解决
    show.setImages( Lists.newArrayList() );
    entityManager.flush();
    

    但我还是不喜欢这个解决方案。

    【讨论】:

      猜你喜欢
      • 2017-10-01
      • 1970-01-01
      • 2019-02-18
      • 2013-10-05
      • 2014-02-19
      • 2020-03-24
      • 2017-05-11
      • 1970-01-01
      • 2021-08-05
      相关资源
      最近更新 更多