[英]Why won't astyanax (java) recognize my @Id annotated values in my scala case class parameter list?
所以這就是我的困境:我有一個域模型,其中包含一些scala中的案例類,例如User
和Organization
。 在我的數據訪問層(dao,存儲庫等)中,我使用的是astyanax(來自netflix的java庫),它的實體持久化將對象保存到cassandra列族。
這是我的cassandra / astyanax支持的DAO的一些示例代碼(是的,我知道我需要做更多的scala-ish,但我還在學習=))
在閱讀了這篇冗長的描述之后,我基本上都在尋找為什么當Java在Field
上執行getDeclaredAnnotations()
時,param列表中的注釋val將無法工作我不想回去並重構所有內容以便我可以使用persister使得保存實體非常簡單(即manager.put(entity)
)。 如果我想繼續使用case類,那么我可以使用更多不可變的樣式scala和scalaz中的Lens
,我將不得不更新DAO並手動執行所有持久化操作,這可以真正消磨時間。
所以,如果有人知道我沒有看到的東西,請告訴我! 提前感謝您花時間閱讀本文。
場景1 - 案例類
Astyanax未能在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)
場景2 - 具有伴隨對象的類或沒有伴隨對象的類
Astyanax未能在val
上獲取@Id注釋
@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 - 在塊內定義val的Case類或類
這樣可以正常工作,因為它選擇帶有@Id
注釋的theId
,但是我不想這樣做,因為IdBaseEntity
已經定義並且id val
並且IdBaseEntity
了繼承的整個目的並且能夠將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而不是case類的參數列表或帶有伴隨對象的常規類/常規類時,我的每個場景都會失敗。 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
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 }
我遇到了一個類似的問題,我的注釋從未在構造函數的字段中考慮過。 實際上,我使用了SpringData,並且不可能直接在一個字段上映射注釋(如@Indexed
)。
要在case類的構造函數中啟用注釋,首先應創建此類:
object FixedScalaAnnotations {
type Id = com.packagecontainingid.Id @field //replace by the right package
type Column = com.packagecontainingcolumn.Column @field
}
然后在您的案例類中導入它並使用它而不是原始類:
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成為一個特質而且一切都很好
這是層次結構
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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.