所以这是我的困境:我有一个域模型,其中有一堆 scala 中的案例类,例如User
and Organization
。在我的数据访问层(dao、存储库等)中,我使用 astyanax(来自 netflix 的 java 库)及其实体持久器将对象保存到 cassandra 列族。
这是我的 cassandra/astyanax 支持的 DAO 的一些示例代码(是的,我知道我需要做一些更 scala 的事情,但我仍在学习=))
读完这个冗长的描述后,我基本上想知道为什么当 java 运行时,参数列表中带注释的 vals 不起作用getDeclaredAnnotations()
on the Field
我不想回去重构一切,这样我就可以使用持久化器,这使得保存实体变得非常简单(即manager.put(entity)
)。如果我想继续使用案例类,这样我就可以使用更不可变的风格 scala 和Lens
从 scalaz 开始,我将不得不更新 DAO 并手动执行所有持久操作,这确实会消磨时间。
所以,如果有人知道我没有看到的东西,请告诉我!预先感谢您花时间阅读本文。
场景 1 - 案例类
Astyanax 无法获取注释 @Idval
@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)
场景 2 - 具有伴生对象的类或不具有伴生对象的类
Astyanax 无法获取 @Id 注释val
@Entity
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)
object Organization {
def apply(id: Option[UUID] = None,
createdOn: Option[Date] = None,
modifiedOn: Option[Date] = None,
name: Option[String] = None,
isPaidAccount: Boolean = false) = new Organization(id, createdOn, modifiedOn, name, isPaidAccount)
}
场景 3 - Case 类或在块内定义 val 的类
这工作正常,因为它会拾取theId
注释为@Id
,但我不想这样做,因为IdBaseEntity
已经定义了并且id val
并破坏了继承和能够传递的全部目的id
到超类
@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) {
@Id @Column(name = "id") val theId: Option[UUID] = id
}
数据访问部分
在管理器的下方,您会看到一个电话build()
。 Astyanax 检查传入的类withEntityType()
,在本例中是classOf[Organization]
我的每个场景都会失败,除了#3,当我在类块内声明一个 val 而不是案例类或带有伴生对象的常规类/常规类的参数列表时。 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 https://github.com/Netflix/astyanax/blob/master/astyanax-entity-mapper/src/main/java/com/netflix/astyanax/entitystore/EntityMapper.java#L89-120
class CassandraOrganizationDAO extends BaseCassandraDAO[Organization, UUID](Astyanax.context) with OrganizationDAO {
val ColumnFamilyOrganizations: ColumnFamily[UUID, String] = new ColumnFamily[UUID, String](
"organizations",
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[Organization, UUID]()
.withEntityType(classOf[Organization])
.withKeyspace(getKeyspace())
.withColumnFamily(ColumnFamilyOrganizations)
.build()
// the rest of the class is omitted
}