Say i have the following class:
class Person {
@BeanProperty
var firstName: String = _
}
Is it possible to get the String representation of "firstName" in a type-safe way, by reflection or something? Or the String representation of the generated "getFirstName"-Function?
It would be nice if it would somehow look like:
val p = new Person
p.getFunction(p.getFirstName).toString // "getFirstName"
p.getAttribute(p.firstName).toString // "firstName"
EDIT
Ok, more explanation is needed ;)
Say i want to build a SQL query like this:
val jpql = "select p from Person p where p.age > 20";
So i want to make it as typesafe as possible and write something like this:
val jpql = "select p from " + classOf[Person].getName + " where p." +
Person.getAttName(p.age) + " > 20";
In this way, if it's possible to refactor Scala code in the future, i could change the attribute name of Person without breaking my code.
The bad news is Scala doesn't really have the ability to reference members like that. You can get a "method reference" like this:
scala> class Person(val firstName:String)
defined class Person
scala> val methodRef = new Person("i").firstName _
methodRef: () => String = <function0>
scala> methodRef()
res1: String = i
But it doesn't give you the reflective stuff that you want. The good news is there are a couple of libraries out there that give you this type of type-safe JDBC. Here's your code using Squeryl:
import org.squeryl.Schema
import org.squeryl.Session
import org.squeryl.PrimitiveTypeMode._
import org.squeryl.adapters.H2Adapter
import org.squeryl.SessionFactory
object Sample {
case class Person(val firstName:String, val age:Int)
object AppSchema extends Schema {
val people = table[Person]("People")
}
def main(args:Array[String]) {
import AppSchema.people
Class.forName("org.h2.Driver")
SessionFactory.concreteFactory = Some(()=> Session.create(java.sql.DriverManager.getConnection("jdbc:h2:~/temp/db", "sa", ""), new H2Adapter))
transaction {
AppSchema.create
people.insert(new Person("ifischer", 92))
people.insert(new Person("baby", 2))
for (olderPerson <- from(people)(p=> where(p.age gt 20) select(p))) {
println(olderPerson) //wont return "baby"!
}
}
}
}
How cool is that? This won't compile if, for example, you try to compare age to a String. Of course it also won't compile if you use p.ssn or some other unknown field.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With