为什么 astyanax (java) 无法识别我的 scala 案例类参数列表中的@Id注释值?



所以这是我的困境:我有一个领域模型,在scala中有一堆case类,如UserOrganization。在我的数据访问层(dao, repository等)中,我使用astyanax(来自netflix的java库),它的实体持久性将对象保存到cassandra列族。

这是我的cassandra/astyanax支持的dao的一些示例代码(是的,我知道我需要做一些更scalish的事情,但我仍在学习=)

读完这篇冗长的描述后,我基本上想看看为什么在参数列表中带注释的值在java对FieldgetDeclaredAnnotations()时不起作用,我讨厌不得不回去重构一切,这样我就可以使用persister,这使得保存实体(即manager.put(entity))变得非常简单。如果我想继续使用case类,这样我就可以使用更具不可变风格的scala和来自scalaz的Lens,那么我就必须更新DAO并手动执行所有的持久化操作,这真的很浪费时间。

所以,如果有人知道我没有看到的东西,请让我知道!提前感谢您花时间阅读这篇文章。

场景1 -案例类

Astyanax无法拾取val上的注释@Id

<>以前@ entitycase class Organization(@Id @Column(name = "id") override val id: Option[UUID] = None,@Column(name = "created_on") override val createdOn: Option[Date] = None,@Column(name = "modified_on") override val modifieddon: Option[Date] = None,@Column(name = "name") name: Option[String] = None,@Column(name = "is_paid_account") isPaidAccount: Boolean = false) extends IdBaseEntity[UUID](id, createdOn, modifieldon)场景2 -类有伴侣对象或没有伴侣对象

Astyanax无法拾取val上的@Id注释

<>以前@ entityclass Organization(@Id @Column(name = "id") override val id: Option[UUID] = None,@Column(name = "created_on") override val createdOn: Option[Date] = None,@Column(name = "modified_on") override val modifieddon: Option[Date] = None,@Column(name = "name") name: Option[String] = None,@Column(name = "is_paid_account") isPaidAccount: Boolean = false) extends IdBaseEntity[UUID](id, createdOn, modifieldon)对象组织{def apply(id: Option[UUID] = None,createdOn: Option[Date] = None,modifieldon: Option[Date] = None,name: Option[String] = None,isPaidAccount: Boolean = false) = new Organization(id, createdOn, modifieldon, name, isPaidAccount)}场景3 -在block中定义val的Case类或类

这工作得很好,因为它拾取theId作为与@Id注释,但我不想这样做,因为IdBaseEntity已经定义和id val,并击败继承的整个目的,并能够将id传递给超类

<>以前@ entitycase class Organization(@Id @Column(name = "id") override val id: Option[UUID] = None,@Column(name = "created_on") override val createdOn: Option[Date] = None,@Column(name = "modified_on") override val modifieddon: Option[Date] = None,@Column(name = "name") name: Option[String] = None,@Column(name = "is_paid_account") isPaidAccount: Boolean = false) extends IdBaseEntity[UUID](id, createdOn, modifieldon) {@Id @Column(name = "id") val theId: Option[UUID] = id}数据访问部分

在管理器中,您将看到对build()的调用。Astyanax检查传递给withEntityType()的类,在本例中是classOf[Organization]

当我在类块中声明了一个val而不是case类的参数列表或带伴体对象的常规类/常规类时,除了#3之外,我的每个场景都失败了。Astyanax说,该类中有一个已知的成员用@Id注释,所以它会抛出异常。在进一步深入研究之前,我想我应该向社区询问注释scala类并将其发送到执行反射的java库的细微差别。来源没什么特别的。事实上,以下是失败的相关行:https://github.com/Netflix/astyanax/blob/master/astyanax-entity-mapper/src/main/java/com/netflix/astyanax/entitystore/EntityMapper.java#L89-120

类CassandraOrganizationDAO扩展BaseCassandraDAO[Organization, UUID](Astyanax.context)与OrganizationDAO {val ColumnFamilyOrganizations: ColumnFamily[UUID, String] = new ColumnFamily[UUID, String]("组织",TimeUUIDSerializer.get (),StringSerializer.get (),ByteBufferSerializer.get ())val ColumnFamilyOrganizationMembers: ColumnFamily[UUID, UUID] = new ColumnFamily[UUID, UUID]("organization_members",TimeUUIDSerializer.get (),TimeUUIDSerializer.get (),DateSerializer.get ())val manager: EntityManager[Organization, UUID] = new DefaultEntityManager。Builder(组织、UUID) ().withEntityType(名为[机构]classOf).withKeyspace (getKeyspace ()).withColumnFamily (ColumnFamilyOrganizations).build ()//类的其余部分被省略}

我遇到了一个类似的问题,在构造函数的字段中从来没有考虑到我的注释。实际上,我使用了SpringData,并且不可能直接在字段上映射注释(如@Indexed)。

要在case类的构造函数中启用注释,首先应该创建这样的类:
object FixedScalaAnnotations {
type Id = com.packagecontainingid.Id @field //replace by the right package
type Column = com.packagecontainingcolumn.Column @field
}

然后将它导入到case类中并使用它来代替原来的:

import FixedScalaAnnotations._
@Entity
case class Organization(@Id @Column(name = "id") override val id: Option[UUID] = None,
@Column(name = "created_on") override val createdOn: Option[Date] = None,
@Column(name = "modified_on") override val modifiedOn: Option[Date] = None,
@Column(name = "name") name: Option[String] = None,
@Column(name = "is_paid_account") isPaidAccount: Boolean = false) extends IdBaseEntity[UUID](id, createdOn, modifiedOn)

请确保不要使用原包。

这里有一篇关于JPA的相关文章:http://blog.fakod.eu/2010/07/14/constructor-arguments-with-jpa-annotations/

@Mik378在处理JPA注释方面提供了很大的帮助,这似乎适用于使用Hibernate之类的东西的人。然而,在我的情况下,我使用的是Astyanax,这可能只是它的一个细微差别,所以我将根据我从上面的@Mike378中学到的东西发布适合我的解决方案。

重要:当IdBaseEntity是一个抽象类或类时,我无法让任何东西工作。

解决方案:我不得不让IdBaseEntity一个trait代替,一切都工作得很好

下面是层次结构

BaseEntity.scala

import java.util.Date
trait BaseEntity {
val createdOn: Option[Date] = None
val modifiedOn: Option[Date] = None
}

IdBaseEntity.scala

trait IdBaseEntity[T <: java.io.Serializable] extends BaseEntity {
val id: Option[T] = None
}

FixedScalaAnnotations.scala

import scala.annotation.meta.field
object FixedScalaAnnotations {
type Id = javax.persistence.Id @field
type Column = javax.persistence.Column @field
}

Organization.scala

import java.util.{Date, UUID}
import FixedScalaAnnotations._
import javax.persistence.Entity
@Entity
case class Organization(@Id @Column(name = "id") override val id: Option[UUID] = None,
@Column(name = "created_on") override val createdOn: Option[Date] = None,
@Column(name = "modified_on") override val modifiedOn: Option[Date] = None,
@Column(name = "name") name: Option[String] = None,
@Column(name = "is_paid_account") isPaidAccount: Boolean = false) extends IdBaseEntity[UUID]

相关内容

  • 没有找到相关文章

最新更新