Shared object load function for scala

I start with a Scala application using Hibernate (JPA) on the back. To load an object, I use this line of code:

val addr = s.load(classOf[Address], addr_id).asInstanceOf[Address]; 

Needless to say, it hurts a little. I wrote a helper class that looks like this:

 import org.hibernate.Session class DataLoader(s: Session) { def loadAddress(id: Long): Address = { return s.load(classOf[Address], id).asInstanceOf[Address]; } ... } 

So now I can do this:

 val dl = new DataLoader(s) val addr = dl loadAddress(addr_id) 

Here's the question: How to write a generic parameterized method that can load any object using the same template? i.e

 val addr = dl load[Address](addr_id) 

(or something like that.)

I'm new to Scala, so please forgive something here, which is especially disgusting.

+4
source share
2 answers

There he is:

 import org.hibernate.Session class DataLoader(s: Session) { def load[A](id: Long)(implicit m: Manifest[A]): A = { return s.load(m.erasure, id).asInstanceOf[A]; } } 

EDIT . Or, to ensure that any casting error - as a result of sleep mode that returns the wrong object - will happen inside load , for example:

 import org.hibernate.Session class DataLoader(s: Session) { def load[A](id: Long)(implicit m: Manifest[A]): A = { return m.erasure.asInstanceOf[Class[A]].cast(s.load(m.erasure, id)); } } 

In Scala 2.8, you can also write it like this:

 import org.hibernate.Session class DataLoader(s: Session) { def load[A : Manifest](id: Long): A = { return s.load(manifest[A].erasure, id).asInstanceOf[A]; } } 

You can combine it with an implicit session as suggested by Chris :

 def load[A](id: Long)(implicit m: Manifest[A], s: org.hibernate.Session): A = { return s.load(m.erasure, id).asInstanceOf[A]; } 

Note that you cannot combine contextual notation ( A : Manifest ) with additional implicit parameters.

+5
source

One method is to use the java.lang.Class.cast method to do something like:

 def load[A](clazz: Class[A], id: Long)(implicit s: Session) : A = clazz.cast(s.load(clazz, id)) 

Then the following is used:

 implicit val s = ...//get hibernate session val addr = load(classOf[Address], 1) 

This is not much different from what you already have, but to access the class instance you need to pass it.

I am sure that you cannot safely do what you want with Manifests , because they cannot provide the parameterized Class[Address] at compile time, which you need for the cast to be executed (they can only erase the Class[_] ) I do not see another mechanism for creating an act with Manifest

Of course, you can use asInstanceOf[A] instead of cast , but this is removed when compiling to isInstanceOf[Object] and is therefore useless from the point of view of checking the type of compilation (and therefore not practical).

+3
source

Source: https://habr.com/ru/post/1303943/


All Articles