2009-07-16 57 views
41

Estoy a punto de escribir una aplicación de línea de comandos Scala que se basa en una base de datos MySQL. He estado buscando ORMs, y estoy teniendo problemas para encontrar uno que funcione bien.¿Qué ORM funcionan bien con Scala?

El Lift ORM se ve bien, pero no estoy seguro de que se pueda desacoplar de todo el marco web Lift. ActiveObjects también se ve bien, pero el autor dice que puede no funcionar bien con Scala.

No voy a venir a Scala desde Java, así que no conozco todas las opciones. ¿Alguien ha usado un ORM con Scala? De ser así, ¿qué utilizó y qué tan bien funcionó?

Respuesta

34

Hay varias razones por las cuales los marcos JPA-orientado (Hibernate, por ejemplo) no encajan en las aplicaciones idiomáticas Scala elegantemente:

  • no hay anotaciones anidadas como establece la Scala 2.8 Preview - que significa que no puede utilizar las anotaciones como metadatos de mapeo para aplicaciones complejas (incluso las más simples a menudo usan @JoinTable ->@JoinColumn);
  • las inconsistencias entre las colecciones de Scala y Java hacen que los desarrolladores conviertan colecciones; también hay casos en los que es imposible mapear colecciones de Scala a asociaciones sin implementar interfaces complejas del marco subyacente (Hibernate's PersistentCollections, por ejemplo);
  • algunas características muy comunes, como la validación del modelo de dominio, requieren convenciones JavaBeans en clases persistentes; estas cosas no son del todo "modo Scala" de hacer las cosas;
  • por supuesto, los problemas de interoperabilidad (como Raw Types o proxies) introducen un nuevo nivel de problemas que no se puede evitar fácilmente.

Existen más razones, estoy seguro. Es por eso que hemos comenzado el Circumflex ORM project. Este ORM de Scala puro trata de eliminar las pesadillas de los clásicos ORM de Java. En concreto, se definen las entidades más o menos en forma que lo haría hacer esto con instrucciones DDL clásicos:

class User extends Record[User] { 
    val name = "name".TEXT.NOT_NULL 
    val admin = "admin".BOOLEAN.NOT_NULL.DEFAULT('false') 
} 

object User extends Table[User] { 
    def byName(n: String): Seq[User] = criteria.add(this.name LIKE n).list 
} 

// example with foreign keys: 
class Account extends Record[Account] { 
    val accountNumber = "acc_number".BIGINT.NOT_NULL 
    val user = "user_id".REFERENCES(User).ON_DELETE(CASCADE) 
    val amount = "amount".NUMERIC(10,2).NOT_NULL 
} 

object Account extends Table[Account] 

Como se puede ver, estas declaraciones son un poco más detallado, que las clásicas APP POJOs.Pero, de hecho, hay varios conceptos que se ensamblan entre sí:

  • el DDL precisa para la generación de esquema (se puede agregar fácilmente los índices, claves externas y otras cosas de la misma manera DSL-similares);
  • todas las consultas se pueden ensamblar dentro de ese "objeto de tabla" en lugar de estar dispersas en DAO; las consultas mismas son muy flexible, puede almacenar objetos de consulta, predicados, proyecciones, subconsultas y alias de relación en variables para que pueda reutilizarlos, e incluso realizar operaciones de actualización por lotes desde consultas existentes (insertar-seleccionar, por ejemplo);
  • navegación transparente entre asociaciones (uno a uno, muchos a uno, uno a muchos y muchos a muchos a través de relaciones intermedias) se puede lograr ya sea por perezoso o por estrategias de búsqueda ansiosas; en ambos casos, las asociaciones se establecen sobre las claves externas de las relaciones subyacentes;
  • la validación es la parte del marco;
  • También hay un plugin Maven2 que permite generar esquemas e importar datos iniciales de archivos con formato XML útiles.

Las únicas cosas circunfleja ORM carece son:

  • llaves de varias columnas principales (aunque es posible crear las claves externas de varias columnas respaldados por restricciones únicas de varias columnas, pero es sólo para integridad de los datos);
  • documentación completa (aunque estamos trabajando activamente en ello);
  • historias de éxito de sistemas de producción de diez mil millones de dólares que tienen Circumflex ORM como su tecnología principal.

P.S. Espero que esta publicación no se considere un anuncio. No es así, en realidad, estaba tratando de ser lo más objetivo posible.

+0

Esto es bastante bueno: estoy deseando echarle un vistazo. –

+3

Genial para ver más atención al espacio ORM en Scala nativo. Otra biblioteca que encontré es http://squeryl.org/. Otorga capacidades de estilo .net Linq a sus consultas. – user127386

9

Experimenté con EclipseLink JPA y las operaciones básicas funcionaron bien para mí. JPA es un estándar de Java y existen otras implementaciones que también pueden funcionar (OpenJPA, etc.). He aquí un ejemplo de lo que una clase de APP en Scala se parece a:

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 

@Entity { val name = "Users" } 
class User { 
    @Id 
    @GeneratedValue 
    var userid:Long = _ 

    var login:String = _ 

    var password:String = _ 

    var firstName:String = _ 

    var lastName:String = _ 
} 
+0

Con EclipseLink uno podría encontrar con algunos problemas de código de bytes, que puede ser fijado mediante el uso de 'nivel de acceso protected' con los campos . – SkyDan

2

aquí es básicamente el mismo ejemplo con @Column anotación:

/* 
    Corresponding table: 

CREATE TABLE `users` (
    `id` int(11) NOT NULL auto_increment, 
    `name` varchar(255) default NULL, 
    `admin` tinyint(1) default '0', 
    PRIMARY KEY (`id`) 
) 

*/ 

import _root_.javax.persistence._ 

@Entity 
@Table{val name="users"} 
class User { 

    @Id 
    @Column{val name="id"} 
    var id: Long = _ 

    @Column{val name="name"} 
    var name: String = _ 

    @Column{val name="admin"} 
    var isAdmin: Boolean = _ 

    override def toString = "UserId: " + id + " isAdmin: " + isAdmin + " Name: " + name 

} 
4

Me complace anunciar el primer lanzamiento de una nueva biblioteca ORM para Scala. MapperDao asigna clases de dominio a tablas de bases de datos. Actualmente es compatible con mysql, postgresql (el controlador oracle estará disponible pronto), uno a uno, muchos a uno, uno a muchos, muchos a varios relaciones, claves autogeneradas, transacciones y opcionalmente se integra muy bien con la primavera marco de referencia. Permite libertad en el diseño de las clases de dominio que no se ven afectadas por los detalles de persistencia, fomenta la inmutabilidad y es seguro. La biblioteca no se basa en la reflexión sino en buenos principios de diseño de Scala y contiene una DSL para consultar datos, que se asemeja mucho a las consultas de selección. No requiere la implementación de métodos equals() o hashCode() que pueden ser problemáticos para entidades persistentes. El mapeo se hace usando el tipo de código Scala seguro.

detalles e instrucciones de uso se pueden encontrar en el sitio del mapperdao:

http://code.google.com/p/mapperdao/

La biblioteca está disponible para su descarga en el sitio arriba y también como una dependencia experto (documentación contiene información detallada sobre cómo usarlo a través de Maven)

ejemplos se pueden encontrar en:

https://code.google.com/p/mapperdao-examples/

muy breve introducción de la biblioteca a través de código de ejemplo:

class Product(val name: String, val attributes: Set[Attribute]) 
class Attribute(val name: String, val value: String) 
... 

val product = new Product("blue jean", Set(new Attribute("colour", "blue"), new Attribute("size", "medium"))) 
val inserted = mapperDao.insert(ProductEntity, product) 
// the persisted entity has an id property: 
println("%d : %s".format(inserted.id,inserted)) 

Consulta es muy familiar:

val o=OrderEntity 

import Query._ 
val orders = query(select from o where o.totalAmount >= 20.0 and o.totalAmount <= 30.0) 
println(orders) // a list of orders 

animo a todos a utilizar la biblioteca y dar retroalimentación. La documentación actualmente es bastante extensa, con instrucciones de instalación y uso. No dude en comentar y ponerse en contacto conmigo en kostas dot kougios en googlemail dot com.

Gracias,

Kostantinos Kougios

2

Slick es un complemento perfecto para un mundo funcional. Los ORM tradicionales no son perfectos para Scala. Slick se compone bien y utiliza una DSL que imita las clases de colección de Scala y para las comprensiones.

1

Por supuesto, cualquier marco de acceso de base de datos Java funcionará también en Scala, con los problemas habituales que puede encontrar, como la conversión de colecciones, etc. Se ha observado que jOOQ, por ejemplo, funciona bien en Scala. Un ejemplo de código de jOOQ en Scala se da en el manual:

object Test { 
    def main(args: Array[String]): Unit = { 
    val c = DriverManager.getConnection("jdbc:h2:~/test", "sa", ""); 
    val f = new Factory(c, SQLDialect.H2); 
    val x = T_AUTHOR as "x" 

    for (r <- f 
     select (
      T_BOOK.ID * T_BOOK.AUTHOR_ID, 
      T_BOOK.ID + T_BOOK.AUTHOR_ID * 3 + 4, 
      T_BOOK.TITLE || " abc" || " xy" 
     ) 
     from T_BOOK 
     leftOuterJoin (
      f select (x.ID, x.YEAR_OF_BIRTH) 
      from x 
      limit 1 
      asTable x.getName() 
     ) 
     on T_BOOK.AUTHOR_ID === x.ID 
     where (T_BOOK.ID <> 2) 
     or (T_BOOK.TITLE in ("O Alquimista", "Brida")) 
     fetch 
    ) { 
     println(r) 
    } 
    } 
} 

Tomado de http://www.jooq.org/doc/2.6/manual/getting-started/jooq-and-scala/

Cuestiones relacionadas