I am designing an API interface in a 2-tier architecture. It takes a string parameter fieldName from URL and returns a JSON string. fieldName refers to a field in my database table. You can think of its signature as:
def controller(fieldName: String): String
In the controller, I would like to call a method in my data access layer to perform the following query:
SELECT fieldName, SUM(salary) FROM Employee GROUP BY fieldName
because the type of the field varies, the type of the query result will be different. This method is parametrized by a generic type parameter T which corresponds to the type of the field with name fieldName.
def getTotalSalaryByField[T](fieldName: String): Map[T, Long]
given a particular fieldName at runtime, how do I call this method giving it the correct type?
I don't want to write a lot of if-else or pattern matching statements to select the type. It would look like this:
fieldName match {
case "age" => serializeToJson(getTotalSalaryByField[Int]("age"))
case "name" => serializeToJson(getTotalSalaryByField[String]("name"))
...
// 100 more for 100 more fields
}
This is ugly. If I were to write this in Python, it will take only one line:
json.dumps(getTotalSalaryByField(fieldName))
Is Scala somehow not suitable for rest backend programming? because this seems to be a common pattern people will encounter, and static typing gets in the way. I would like to see some suggestions as to how I should approach the whole problem in scala-ish way, even if it means remodeling, rewriting the DAL and controllers.
EDIT: @drexin, the actual signature of the DAL method is
def myDAOMethod[T](tf: Option[TimeFilter], cf: CrossFilter)
(implicit attr: XFAttribute[T]): Map[T, Long]
T is the type of fieldName. Long is the type of y. As you can see, I need to select a type to be T based on fieldName from url parameter.
EDIT: added some code and made the usecase clear
There is a difference between knowing the type of a variable at compile time and at runtime.
If the fieldName is not known at compile time (i.e. it's a parameter), and if the type of the column varies by fieldName, then you are not going to be able to specify the return type of the method at compile time.
You will need to use a DAO method that returns AnyRef, rather than one which returns T for a compile-time-specified type T.
The database access library can return the values without needing to know their type, and your code needs to do the same.
You are looking to use a DAO method which takes a type param T:
def myDAOMethod[T](tf: Option[TimeFilter], cf: CrossFilter)
(implicit attr: XFAttribute[T]): Map[T, Long]
... but as you state, you don't know the type T in advance, so this method is inapplicable. (T is used to convert the database column data into a String or an Int).
Your DAO should offer an untyped version of this method, something more like:
def doSelect(tf: Option[TimeFilter], cf: CrossFilter): Map[AnyRef, Long]
What database access library are you using?
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