【问题标题】:Hibernate 4.2.2 not validating entity upon insertion into its @OneToMany CollectionHibernate 4.2.2 在插入其@OneToMany 集合时不验证实体
【发布时间】:2013-12-14 16:50:18
【问题描述】:

我有一个父实体与其子实体具有 OneToMany 关联:

Parent {
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "parent", fetch = FetchType.EAGER)
    @Size(min = 0, max = 4)
    List<Child> children = new ArrayList<Child>();

    @Transactional
    public void addChild(Child child) {
        child.setParent(this);
        children.add(child);
    }
}

当我调用 addChild() 方法时,Hibernate 不会验证子集合 @Size 约束并保持子“原样”,这会导致数据库中的实体无效。

为什么 Hibernate 不验证父实体?

【问题讨论】:

    标签: java hibernate hibernate-validator


    【解决方案1】:

    Hibernate 会为子实体触发 INSERT,但不会为父实体触发 UPDATE。我调试了 Hibernate 源代码,发现org/hibernate/event/internal/DefaultFlushEntityEventListener.java:isUpdateNecessary() 在上述情况下返回false。看起来这是一个必须修复的错误。

    一种可能的解决方案是进行“虚假”更改,这会弄脏实体并触发验证过程。

    【讨论】:

      【解决方案2】:

      我认为hibernate不应该在调用“add”方法时进行验证,通常验证是在持久化时触发的(或者可能是其他一些情况)。

      /**
       * @author Zilvinas Vilutis
       */
      public class CollectionSizeTest {
      
          private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
          private final Validator validator = factory.getValidator();
      
          public class CollectionSize {
              @Size( min = 0, max = 1 )
              private Collection<String> collection = new ArrayList<String>();
      
          }
      
          @Test
          public void testCollectionSize() {
              CollectionSize underTest = new CollectionSize();
              assertTrue( validator.validate( underTest ).isEmpty() );
      
              underTest.collection.add( "first" );
              assertTrue( validator.validate( underTest ).isEmpty() );
      
              underTest.collection.add( "second" );
              assertEquals( 1, validator.validate( underTest ).size() );
              assertEquals( "size must be between 0 and 1", validator.validate( underTest ).iterator().next().getMessage() );
          }
      
      }
      

      【讨论】:

      • 该方法被注释为@Transactional - persist() 将被隐式调用
      • 我想知道 @Transactional 如何在域实体类上为您工作,因为 Spring 将其方面附加在包扫描配置中定义的 spring bean 上。我建议将其移至服务中。
      • 在我的情况下这是一个@Configurable 类,我有意使用活动记录模式。不过,感谢您的建议;)
      猜你喜欢
      • 1970-01-01
      • 2021-12-21
      • 2011-12-15
      • 2012-10-02
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 2020-03-03
      • 1970-01-01
      相关资源
      最近更新 更多