편집 : 질문을 다시 작성하십시오. 나를 위해 중요성을 알린 바운티를 추가했습니다. findByAttributes를 (서브 클래스에서 다시 구현하지 않고) 얻을 수있는 최종 힌트는 내 포인트를 얻을 것이다.제네릭 메서드 구현을 추상 수퍼 클래스로 이동
내 응용 프로그램에서는 새로운 JPA2 기준 쿼리를 사용하여 typesafe 데이터베이스 쿼리를 수행하고 있습니다. 따라서 필자는 응용 프로그램의 모든 엔티티에서 사용할 수 있어야하는 특성 DAO를 가지고 있습니다. 그래서이 방법 (작동) 같은 내가 외모를 사용하고 현재 특징 개요 : 콘크리트의 DAO에서
trait DAO[T, K](implicit m: Manifest[T]) {
@PersistenceContext
var em:EntityManager = _
lazy val cb:CriteriaBuilder = em.getCriteriaBuilder
def persist(entity: T)
def update(entity: T)
def remove(entity: T)
def findAll(): ArrayList[T]
// Pair of SingularAttribute and corresponding value
// (used for queries for multiple attributes)
type AttributeValuePair[A] = Pair[SingularAttribute[T, A], A]
// Query for entities where given attribute has given value
def findByAttribute[A](attribute:AttributeValuePair[A]):ArrayList[T]
// Query for entities with multiple attributes (like query by example)
def findByAttributes[A](attributes:AttributeValuePair[_]*):ArrayList[T]
}
, 난이 같은이 특성을 확장하고있어, 방법을 유형을 설정하고 실행 (가장 중요한 방법을 제외하고 모두 제거됨) :
class UserDAO extends DAO[User, Long] {
override type AttributeValuePair[T] = Pair[SingularAttribute[User, T], T]
override def findByAttributes[T](attributes:AttributeValuePair[_]*):ArrayList[User] = {
val cq = cb.createQuery(classOf[User])
val queryRoot = cq.from(classOf[User])
var criteria = cb.conjunction
for (pair <- attributes)
criteria = cb.and(cb.equal(queryRoot.get(pair._1), pair._2))
cq.where(Seq(criteria):_*)
val results = em.createQuery(cq).getResultList
results.asInstanceOf[ArrayList[User]]
}
}
현재로서는 findByAttributes를 사용하는 것이 좋습니다. 예 :
val userList = userEJB.findByAttributes(
User_.title -> Title.MR,
User_.email -> "[email protected]"
)
나는 깨달았다, 그 findByAttributes
는 DAO를 구현하는 내 응용 프로그램의 모든 클래스에서 자사의 같은, 그래서 일반적이다. 변경되는 유일한 방법은 메서드에서 사용되는 유형입니다. 다른 클래스 느릅 나무는 DAO를 상속에서 그래서 그
def findByAttributes[T](attributes:AttributeValuePair[_]*):ArrayList[Message] = {
val cq = cb.createQuery(classOf[Message])
val queryRoot = cq.from(classOf[Message])
var criteria = cb.conjunction
for (pair <- attributes)
criteria = cb.and(cb.equal(queryRoot.get(pair._1), pair._2))
cq.where(Seq(criteria):_*)
val results = em.createQuery(cq).getResultList
results.asInstanceOf[ArrayList[User]]
}
그래서 나는 모든 서브 클래스에서 그들을 다시 구현하지 않아도, 구현 된 일반적인 방법을 포함해야 SuperDAO라는 새로운 추상 클래스를 만들었습니다. Landei (감사), 내 SuperDAO의 현재 구현 (내의 가장 중요한 부분)의 도움이
abstract class SuperDAO[T, K](implicit m: Manifest[T]) {
@PersistenceContext
var em:EntityManager = _
lazy val cb:CriteriaBuilder = em.getCriteriaBuilder
type AttributeValuePair[A] = Pair[SingularAttribute[T, A], A]
def findByAttributes(attributes:AttributeValuePair[_]*):ArrayList[T] = {
val cq = cb.createQuery(m.erasure)
val queryRoot = cq.from(m.erasure)
var criteria = cb.conjunction
for (pair <- attributes) {
criteria = cb.and(
cb.equal(
// gives compiler error
queryRoot.get[SingularAttribute[T,_]](pair._1)
)
,pair._2
)
}
cq.where(Seq(criteria):_*)
val results = em.createQuery(cq).getResultList
results.asInstanceOf[ArrayList[T]]
}
처럼 보인다 후 그래서 현재의 문제 queryRoot.get와 선이 다음과 같은 오류가 발생한다는 것입니다 :
overloaded method value get with alternatives:
(java.lang.String)javax.persistence.criteria.Path
[javax.persistence.metamodel.SingularAttribute[T, _]] <and>
(javax.persistence.metamodel.SingularAttribute[_ >: Any,
javax.persistence.metamodel.SingularAttribute[T,_]])
javax.persistence.criteria.Path
[javax.persistence.metamodel.SingularAttribute[T, _]]
cannot be applied to
(javax.persistence.metamodel.SingularAttribute[T,_$1])
$ 1은 무엇을 의미합니까 ???
이 필요한 경우 : SingularAttribute Javadoc
편집 @Landei :
가에서
queryRoot.get[A](pair._1.asInstanceOf[SingularAttribute[T,A]])
결과에
def findByAttributesOld[A](attributes:AttributeValuePair[A]*):ArrayList[T] = {
그리고 queryRoot.get에 메소드 서명 변경 (훨씬 짧음 !) 오류 :
overloaded method value get with alternatives:
(java.lang.String)javax.persistence.criteria.Path[A] <and>
(javax.persistence.metamodel.SingularAttribute[_ >: Any, A])
javax.persistence.criteria.Path[A] cannot be applied to
(javax.persistence.metamodel.SingularAttribute[T,A])
@Sandor Murakozi의 솔루션은 작동하는 것 같다. 조금 테스트 해봐. 그러나 나는 가능한 한 더 짧은 해결책을 고맙게 생각합니다! (?)
일반적인 용어주의가 적용됩니다 : 코드 줄 바꿈없이 상자에 맞도록
내가 몇 가지 이름을 단축 당신이 쓸 때'데프 FBA (...) : SomeType = {... }'함수가 아닌 * 메소드 *를 정의하고 있습니다. Scala에서 함수를 가져 오는 데는 여러 가지 방법이 있습니다. 예 :, 부분적인 어플리케이션으로, 메소드를 상응하는 함수로 옮기는 데 사용할 수 있습니다 :'def mFBA (...) : ... = {...}; val fFBA = mFBA _'입니다. –나는 두 권리 사이의 구별을 결코 얻지 못할 것이다. 그러나 당신의 의견은 도움이된다. "function"을 "method"로 대체했습니다. – ifischer
"def findByAttributesOld [A] ..."버전 정보 : 속성 목록이 실제로 균질하지 않기 때문에 매우 정확하지 않다고 생각합니다. Int 및 String 특성이므로 A는 결국 Any가됩니다 (적어도 가장 일반적인 경우). 또한 도움이 될지 확신 할 수 없습니다. 실존 유형 문제에 대한 제 추측이 맞다면 그렇게 생각하지 않습니다. –