Liftweb - Maximum value of a SQL table field with mapper
题
I would like to find a simple way to access the maximum value of a Mapped element in liftweb, here is an example of what I actually do:
Mapper part
class MappedEntity extends LongKeyedMapper[MappedEntity] with IdPK {
def getSingleton = MappedEntity
object targetRaw extends MappedInt(this)
}
object MappedEntity extends MappedEntity with LongKeyedMetaMapper[MappedEntity]
Search part
val max = MappedEntity.findAllByInsecureSql(
"SELECT MAX (targetRaw) AS targetRaw FROM MappedEntity",
IHaveValidatedThisSQL("chris", "2011,11,14")
).head.targetRaw.get
When supposing that I work with the SQL table called MappedEntity, I want max
to contain either a string
or an int
equal to the maximum value contained in targetRaw
If you have any suggestion or any question I will be happy to help.
解决方案
I don't believe that lift-mapper has a built-in way of running this query. In fact, it's very short on any sort of aggregate functions. All I see are some count
methods.
The find*
methods are only suitable for returning objects of the Mapper
s type, as you can see by their return types.
Given that there's no great way to do this in Lift as it stands, you have several options to choose from.
Use lift-squeryl-record instead of lift-mapper. Squeryl is a more complete ORM, and supports group and aggregate functions.
Create your own trait which adds
max
functions to aMetaMapper
. This would be a bit of work, but you can use the implementation ofcount
as a guide.- Technically, there could be a more general implementation that handles all of the aggregate functions (max, min, sum, count, ...). That may be what we in the business call 'overkill'.
Just write some SQL. Lift offers a loan-pattern way of obtaining a connection to the database. It also has loan-pattern helpers for preparing statements and executing queries in such a was that everything is automagically closed when you're done with it.
DB.use(DefaultConnectionIdentifier) { conn => // execute query }
Find the object with the value your looking for, then just retrieve that field. This has the distinct disadvantage of being ugly, slow and brittle.
val max: Option[String] = MappedEntity.findAll( BySql("targetRaw IN (SELECT MAX (targetRaw) FROM MappedEntity)", IHaveValidatedThisSQL("chris", "2011,11,14")).map(_.targetRaw.is).headOption
其他提示
Here is the solution I finally used:
val max = DB.runQuery("SELECT YEAR(MAX(targetRaw)) FROM targetTable")._2.head.head.toInt