Scala 中的 JPA 和 "anonymous" 类

JPA and "anonymous" classes in scala

我有点卡住了,不明白发生了什么。 这个不行

@Entity
@DynamicInsert
@DynamicUpdate
@SelectBeforeUpdate
@Table
class Entity {
  @Column(nullable = false)
  var owner: String = _
}


    val myEntity = new Entity() {
            owner = "some owner 1"
          }
      session.persist(myEntity)

Hibernate 抛出异常:

java.lang.IllegalArgumentException: Unknown entity:persistence.dao.EntityDaoTest$$anonfun$$anonfun$$anon
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:777)

这个有效:

val myEntity = new Entity()
entity.owner = "some owner 1"
session.persist(myEntity)

为什么?为什么休眠无法识别我的 Entity 实例?

更新: @Sheinbergon,谢谢,很清楚。我完全忘记了注释丢失了。有没有可能用一些快捷方式设置实体字段? 写作

val myEntity = new MyEntity()
myEntity.owner = "some owner"
myEntity.someOtherProperty = "value"

超级无聊

还有一个问题 这个有效:

val parent = new Parent
    parent.owner = "Our parent"
    parent.addChild(new Child() {
      name = "First parent's child"
      addGrandChild(new GrandChild() {
        name = "Grand child name"
        addGrandGrandChild(new GrandGrandChild() {
          name = "Grand Grand child name"
          address = new Address() {
            id = 1L
          }
        })
      })
    })

为什么? Child、GrandChild、GrandGrandChild 也是匿名创建的。 addChild、addGrandChild、addGrandGrandChild 只是列表修改器。

def addChild(child: Child): Unit = {
    if (children == null) {
      children = new util.ArrayList[Child]()
    }
    if (Option(child.parent).isEmpty) {
      child.parent = this
    }
    children.add(child)
  }

你在这里做的是在 Scala 中匿名实例化一个 class ,好吧......创建你的 class Entity 的匿名实现(就像匿名实例化一个接口在 Java).

您可以通过打印 class 名称来查看 - println(myEntity.getClass) 在这两种情况下

应用于原始class的注释不适用于匿名注释(反射仍然可以在超级class中找到它们,但这取决于扫描它们的代码)我想那是为什么你会收到各种 JPA 异常

回应您添加的子问题

  • 关于快捷方式 - 为什么不为工厂使用伴随对象或将此 class 转换为案例 class(使用默认值),以实现更好、更灵活的初始化。
  • 关于第二个对象图(并假设每个 classes 都被注释了)——这又取决于反射代码如何处理它扫描的对象。有可能(并且更有可能,因为它不会扫描集合中的每个成员以获取注释)它从已擦除的类型中获取注释定义(可能将其 FQDN class 名称作为 ParameterizedType in Java 对集合的反射 API) 而不是来自集合的实际成员,这就是它起作用的原因。 我不太确定它对字段定义做了什么(它们只存在于 "super" class 中),但是这里没有 "magic",只有普通的旧反射扫描。