Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get name of class-attribute or class-function as String

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.

like image 754
Wolkenarchitekt Avatar asked Dec 03 '25 09:12

Wolkenarchitekt


1 Answers

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.

like image 174
Adam Rabung Avatar answered Dec 04 '25 23:12

Adam Rabung



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!