The orm Package
Package orm contains different shortcuts, utilities, helpers and implicits — the basis of DSL of Circumflex ORM.
You should import this package to use Circumflex ORM in your application:
import ru.circumflex.orm._
|
package object orm {
val ORM_LOG = new Logger("ru.circumflex.orm")
// Commons
val dialect: Dialect = cx.instantiate[Dialect]("orm.dialect", cx.get("orm.connection.url") match {
case Some(url: String) =>
if (url.startsWith("jdbc:postgresql:")) new PostgreSQLDialect
else if (url.startsWith("jdbc:mysql:")) new MySQLDialect
else if (url.startsWith("jdbc:oracle:")) new OracleDialect
else if (url.startsWith("jdbc:h2:")) new H2Dialect
else if (url.startsWith("jdbc:sqlserver:")) new MSSQLDialect
else if (url.startsWith("jdbc:db2:")) new DB2Dialect
else new Dialect
case _ => new Dialect
})
val connectionProvider: ConnectionProvider = cx.instantiate[ConnectionProvider](
"orm.connectionProvider", new DefaultConnectionProvider)
val typeConverter: TypeConverter = cx.instantiate[TypeConverter](
"orm.typeConverter", new TypeConverter)
val transactionManager: TransactionManager = cx.instantiate[TransactionManager](
"orm.transactionManager", new DefaultTransactionManager)
val defaultSchema: Schema = new Schema(
cx.get("orm.defaultSchema").map(_.toString).getOrElse("public"))
val ehcacheManager: CacheManager = cx.get("orm.ehcache.config") match {
case Some(f: String) => new CacheManager(f)
case _ => new CacheManager()
}
def contextCache = CacheService.get
def tx: Transaction = transactionManager.get
def COMMIT() = tx.commit()
def ROLLBACK() = tx.rollback()
|
Alias Stack
Circumflex ORM offers nice DSL to reference fields of aliased tables:
val co = Country AS "co"
val predicate = co.name EQ "Switzerland"
In this example RelationNode[Country] with alias "co" is implicitly converted into Country , its underlying Relation , because only that relation owns field name . However, the information about the alias is lost during this conversion. We use aliasStack to remember it during conversion so it can be accessed later.
|
object aliasStack {
protected def _stack: Stack[String] = ctx.get("orm.aliasStack") match {
case Some(s: Stack[String]) => s
case _ =>
val s = Stack[String]()
ctx += "orm.aliasStack" -> s
s
}
def pop: Option[String] = if (_stack.size == 0) None else Some(_stack.pop)
def push(alias: String): Unit = _stack.push(alias)
}
// Implicits
// for nodes
implicit def relation2node[PK, R <: Record[PK, R]](relation: Relation[PK, R]): RelationNode[PK, R] =
new RelationNode[PK, R](relation)
implicit def node2relation[PK, R <: Record[PK, R]](node: RelationNode[PK, R]): R = {
aliasStack.push(node.alias)
node.relation.asInstanceOf[R]
}
implicit def vh2colExpr[T, R <: Record[_, R]](vh: ValueHolder[T, R]): ColumnExpression[T, R] =
new ColumnExpression(vh)
implicit def str2expr(str: String): SimpleExpression = prepareExpr(str)
// for predicates
implicit def string2helper(expression: String): SimpleExpressionHelper =
new SimpleExpressionHelper(expression)
implicit def string2predicate(expression: String): Predicate =
new SimpleExpression(expression, Nil)
implicit def expr2predicate(expression: Expression): Predicate =
new SimpleExpression(expression.toSql, expression.parameters)
implicit def predicate2aggregateHelper(predicate: Predicate) =
new AggregatePredicateHelper(predicate)
implicit def boolean2predicate(f: BooleanField[_]): Predicate =
string2predicate(f.aliasedName)
// for orders
implicit def string2order(expression: String): Order =
new Order(expression, Nil)
implicit def vh2order(vh: ValueHolder[_, _]): Order =
new Order(vh.aliasedName, Nil)
// for projections
implicit def string2projection(expression: String): Projection[Any] =
new ExpressionProjection[Any](expression)
implicit def vh2projection[T](vh: ValueHolder[T, _]): Projection[T] =
new ExpressionProjection[T](vh.aliasedName)
implicit def pair2proj[T1, T2](t: (Projection[T1], Projection[T2])) =
new PairProjection(t._1, t._2)
// Constants
val NO_ACTION = ForeignKeyAction(dialect.fkNoAction)
val CASCADE = ForeignKeyAction(dialect.fkCascade)
val RESTRICT = ForeignKeyAction(dialect.fkRestrict)
val SET_NULL = ForeignKeyAction(dialect.fkSetNull)
val SET_DEFAULT = ForeignKeyAction(dialect.fkSetDefault)
val INNER = JoinType(dialect.innerJoin)
val LEFT = JoinType(dialect.leftJoin)
val RIGHT = JoinType(dialect.rightJoin)
val FULL = JoinType(dialect.fullJoin)
val OP_UNION = SetOperation(dialect.UNION)
val OP_UNION_ALL = SetOperation(dialect.UNION_ALL)
val OP_EXCEPT = SetOperation(dialect.EXCEPT)
val OP_EXCEPT_ALL = SetOperation(dialect.EXCEPT_ALL)
val OP_INTERSECT = SetOperation(dialect.INTERSECT)
val OP_INTERSECT_ALL = SetOperation(dialect.INTERSECT_ALL)
// Predicates DSL
def AND(predicates: Predicate*) =
new AggregatePredicateHelper(predicates.head).AND(predicates.tail: _*)
def OR(predicates: Predicate*) =
new AggregatePredicateHelper(predicates.head).OR(predicates.tail: _*)
def NOT(predicate: Predicate) =
new SimpleExpression(dialect.not(predicate.toSql), predicate.parameters)
def expr[T](expression: String): ExpressionProjection[T] =
new ExpressionProjection[T](expression)
def prepareExpr(expression: String, params: Pair[String, Any]*): SimpleExpression = {
var sqlText = expression
var parameters: Seq[Any] = Nil
val paramsMap = Map[String, Any](params: _*)
val pattern = Pattern.compile(":(\\w+)\\b")
val matcher = pattern.matcher(expression)
while(matcher.find) paramsMap.get(matcher.group(1)) match {
case Some(param) => parameters ++= List(param)
case _ => parameters ++= List(null)
}
sqlText = matcher.replaceAll("?")
return new SimpleExpression(sqlText, parameters)
}
// Simple subqueries DSL
def EXISTS(subquery: SQLQuery[_]) =
new SubqueryExpression(dialect.EXISTS, subquery)
def NOT_EXISTS(subquery: SQLQuery[_]) =
new SubqueryExpression(dialect.NOT_EXISTS, subquery)
// Simple projections
def COUNT(expr: Expression): Projection[Long] =
new ExpressionProjection[Long](dialect.COUNT(expr.toSql))
def COUNT_DISTINCT(expr: Expression): Projection[Long] =
new ExpressionProjection[Long](dialect.COUNT_DISTINCT(expr.toSql))
def MAX(expr: Expression): Projection[Any] =
new ExpressionProjection[Any](dialect.MAX(expr.toSql))
def MIN(expr: Expression) =
new ExpressionProjection[Any](dialect.MIN(expr.toSql))
def SUM(expr: Expression) =
new ExpressionProjection[Any](dialect.SUM(expr.toSql))
def AVG(expr: Expression) =
new ExpressionProjection[Any](dialect.AVG(expr.toSql))
// Queries DSL
def SELECT[T](p1: Projection[T], p2: Projection[_], pn: Projection[_]*) = {
val projections = List(p1, p2) ++ pn
new Select(new AliasMapProjection(projections))
}
def SELECT[T](projection: Projection[T]): Select[T] = new Select(projection)
def INSERT_INTO[PK, R <: Record[PK, R]](relation: Relation[PK, R]) =
new InsertSelectHelper(relation)
def UPDATE[PK, R <: Record[PK, R]](node: RelationNode[PK, R]) =
new Update(node)
def DELETE[PK, R <: Record[PK, R]](node: RelationNode[PK, R]) =
new Delete(node)
}
|