【发布时间】:2014-12-23 22:31:19
【问题描述】:
考虑到给定的代码:
val repository =
context.getBean(
Introspector.decapitalize(t.getClass.getSimpleName).replace("C", "E").concat("Repository"))
并且我的存储库有一个可序列化的字符串。
我正在尝试执行以下操作:
repository.asInstanceOf[ElasticsearchRepository[_, String]].save(getObject(t))
这个很好用:
repository.asInstanceOf[ElasticsearchRepository[_, String]].findAll()
但我不知道如何把它放在上面。
假设方法 getObject(t) 正在重新调整要持久化的正确对象,并且由于它是 Spring Data Repository,因此有 2 个保存方法。一个接受单个实体,另一个接受实体列表,它说重载方法值保存。
到目前为止我所尝试的:
我在另一个线程中看到强制使用类型的方法,如下所示:
repository.asInstanceOf[ElasticsearchRepository[_, String]].save(getObject(t) : TYPE)
如果我知道类型就可以了,而且我的方法 getObject 应该返回相同的类型。
这是我的 getObject 方法,我返回的对象本身没有任何特定类型:
@throws[IOException]
def getObject[T](t : T) = {
objectMapper.readValue(objectMapper.writeValueAsString(t), getClazz(t))
}
所以我试图得到这样的类型:
val m = Manifest.classType(getClazz(t))
type TYPE = m.type
如果我使用getObject(t) : TYPE 将我的对象强制为这种类型看起来不错,但我不知道如何在要返回的 getObject 方法中使用这种相同类型。
无论如何,我什至不知道这是否是最好的方法,调用通用存储库并保存通用对象。
只是为了理解我想要做什么,我正在使用一个方面来拦截要持久化的 Cassandra 实体,然后获取它并转换为 ElasticSearch 实体以保存 json(这就是为什么 getObject(t) ) 并复制到 ElasticSearch 中。
这是完整的方面类:
@Component
@Aspect
class ElasticAop {
@Autowired val context : ApplicationContext = null
val objectMapper : ObjectMapper = new ObjectMapper()
@Pointcut("execution(* com.test.service.cassandra.*.post(..)) && args(t)")
def getPointcutPost[T](t : T) : Unit = {}
@throws[Throwable]
@Before("getPointcutPost(t)")
def elasticSaveAspect[T](joinPoint: JoinPoint, t: T) = {
val m = Manifest.classType(getClazz(t))
type TYPE = m.type
val repository =
context.getBean(
Introspector.decapitalize(t.getClass.getSimpleName).replace("C", "E").concat("Repository"))
repository.asInstanceOf[ElasticsearchRepository[_, String]].findAll()
repository.asInstanceOf[ElasticsearchRepository[_, String]].save(getObject(t))
}
@throws[ClassNotFoundException]
def getClazz[T](t : T) = {
val className = t.getClass.getName.replace("cassandra", "elastic").replace("C", "E")
Class.forName(className)
}
@throws[IOException]
def getObject[T](t : T) = {
objectMapper.readValue(objectMapper.writeValueAsString(t), getClazz(t))
}
}
已编辑
即使在我的 getObject 中将类型返回设置为 Address,然后将保存方法设置为如下 save(getObject(t) : Address) 也会给我同样的重载错误。
已编辑
我刚刚发现这是一个限制,可能的解决方法是创建一个工厂或类似的东西。 然后我用 saveOrUpdate 方法创建了一个服务:
trait ElasticGenericService[T <: ElasticGenericKey, R <: ElasticsearchRepository[T, String]] {
var r : R = _
def saveOrUpdate(t: T) = r.save(t)
}
现在我遇到了演员表异常:
java.lang.ClassCastException: Address cannot be cast to scala.runtime.Nothing$
【问题讨论】:
标签: spring scala generics spring-data aspectj