Quels ORM fonctionnent bien avec Scala?

Je suis sur le point d’écrire une application de ligne de commande Scala qui s’appuie sur une firebase database MySQL. J’ai cherché des ORM et j’ai du mal à en trouver un qui fonctionnera bien.

L’ ascenseur ORM a l’ air sympa, mais je ne suis pas sûr qu’il puisse être découplé de l’ensemble du framework Web Lift. ActiveObjects semble également OK, mais l’auteur dit que cela ne fonctionnera pas bien avec Scala.

Je ne viens pas de Scala en Java, donc je ne connais pas toutes les options. Quelqu’un a-t-il utilisé un ORM avec Scala, et si oui, qu’avez-vous utilisé et à quel point cela a-t-il fonctionné?

Il y a plusieurs raisons pour lesquelles les frameworks orientés JPA (Hibernate, par exemple) ne s’intègrent pas élégamment dans les applications Scala idiomatiques:

  • il n’y a pas d’annotations nestedes comme l’ aperçu Scala 2.8 – cela signifie que vous ne pouvez pas utiliser les annotations comme métadonnées de mappage pour les applications complexes (même les plus simples utilisent souvent @JoinTable -> @JoinColumn );
  • les incohérences entre les collections Scala et Java font que les développeurs convertissent les collections; il existe également des cas où il est impossible de mapper des collections Scala à des associations sans implémenter des interfaces complexes de la structure sous-jacente ( PersistentCollections d’Hibernate, par exemple);
  • Certaines fonctionnalités très courantes, telles que la validation des modèles de domaine, requièrent des conventions JavaBeans sur les classes persistantes.
  • Bien sûr, les problèmes d’interopérabilité (comme les types bruts ou les proxys) introduisent un tout nouveau niveau de problèmes qui ne peuvent pas être facilement contournés.

Il y a plus de raisons, j’en suis sûr. C’est pourquoi nous avons lancé le projet Circumflex ORM . Cet ORM pur Scala essaie de supprimer les cauchemars des ORM Java classiques. Plus précisément, vous définissez vos entités à peu près comme vous le feriez avec les instructions DDL classiques:

 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: Ssortingng): 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] 

Comme vous pouvez le voir, ces déclarations sont un peu plus détaillées que les JPO classiques. Mais en fait, plusieurs concepts sont assemblés:

  • le DDL précis pour générer un schéma (vous pouvez facilement append des index, des clés étrangères et d’autres éléments du même type DSL);
  • toutes les requêtes peuvent être assemblées à l’intérieur de cet “object table” au lieu d’être dispersées dans DAO; les requêtes elles-mêmes sont très flexibles, vous pouvez stocker des objects de requête, des prédicats, des projections, des sous-requêtes et des alias de relation dans des variables pour les réutiliser et même effectuer des opérations de mise à jour par lot à partir de requêtes existantes (insert-select par exemple);
  • la navigation transparente entre les associations (relation un à un, plusieurs à un, un à plusieurs et plusieurs à plusieurs à travers une relation intermédiaire) peut être obtenue par des stratégies de récupération paresseuses ou avides; dans les deux cas, les associations sont établies au-dessus des clés étrangères des relations sous-jacentes;
  • la validation fait partie du cadre;
  • Il existe également un plug-in Maven2 qui permet de générer des schémas et d’importer des données initiales à partir de fichiers au format XML pratiques.

Les seules choses qui manquent à Circumflex ORM sont:

  • clés primaires multi-colonnes (bien qu’il soit possible de créer des clés étrangères multi-colonnes soutenues par des contraintes uniques multi-colonnes, mais uniquement pour l’intégrité des données);
  • documentation complète (même si nous y travaillons activement);
  • exemples de réussite de systèmes de production de dix milliards de dollars dotés de la technologie de base Circumflex ORM.

PS J’espère que cet article ne sera pas considéré comme une publicité. Ce n’est pas vrai, j’essayais d’être aussi objective que possible.

J’ai expérimenté avec EclipseLink JPA et les opérations de base ont bien fonctionné pour moi. JPA est un standard Java et d’autres implémentations peuvent également fonctionner ( OpenJPA , etc.). Voici un exemple de ce à quoi ressemble une classe JPA à Scala:

 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:Ssortingng = _ var password:Ssortingng = _ var firstName:Ssortingng = _ var lastName:Ssortingng = _ } 

Je suis heureux d’annoncer la première version d’une nouvelle bibliothèque ORM pour Scala. MapperDao mappe les classes de domaine aux tables de firebase database. Il prend actuellement en charge mysql, postgresql (pilote Oracle à être bientôt disponible), un-à-un, plusieurs-à-un, un-à-plusieurs, plusieurs-à-plusieurs relations, clés générées automatiquement, transactions et s’intègre éventuellement avec Spring cadre. Il offre une liberté sur la conception des classes de domaine qui ne sont pas affectées par les détails de la persistance, encourage l’immuabilité et est de type sécurisé. La bibliothèque n’est pas basée sur la reflection mais sur de bons principes de conception Scala et contient un DSL pour interroger les données, qui ressemble étroitement à des requêtes sélectionnées. Cela ne nécessite pas l’implémentation des méthodes equals () ou hashCode () qui peuvent être problématiques pour les entités persistantes. Le mappage est effectué à l’aide du code Scala sécurisé.

Les détails et les instructions d’utilisation peuvent être trouvés sur le site de mapperdao:

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

La bibliothèque est disponible en téléchargement sur le site ci-dessus et également en tant que dépendance de maven (la documentation contient des détails sur son utilisation via maven)

Des exemples peuvent être trouvés à:

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

Très brève introduction de la bibliothèque via un exemple de code:

 class Product(val name: Ssortingng, val atsortingbutes: Set[Atsortingbute]) class Atsortingbute(val name: Ssortingng, val value: Ssortingng) ... val product = new Product("blue jean", Set(new Atsortingbute("colour", "blue"), new Atsortingbute("size", "medium"))) val inserted = mapperDao.insert(ProductEntity, product) // the persisted entity has an id property: println("%d : %s".format(inserted.id,inserted)) 

Interroger est très familier:

 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 

J'encourage tout le monde à utiliser la bibliothèque et à donner son avis. La documentation est actuellement très complète, avec des instructions d'installation et d'utilisation. S'il vous plaît n'hésitez pas à commenter et entrer en contact avec moi à kostas dot kougios à googlemail dot com.

Merci,

Kostantinos Kougios

Voici essentiellement le même exemple avec l’annotation @Column:

  /* 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: Ssortingng = _ @Column{val name="admin"} var isAdmin: Boolean = _ override def toSsortingng = "UserId: " + id + " isAdmin: " + isAdmin + " Name: " + name } 

Slick est un match parfait pour un monde fonctionnel. Les ORM traditionnels ne conviennent pas parfaitement à Scala. Slick compose bien et utilise un DSL qui imite les classes de collection Scala et pour les comprendre.

Bien entendu, toute structure d’access à la firebase database Java fonctionnera également dans Scala, avec les problèmes habituels que vous pouvez rencontrer, tels que la conversion des collections, etc. jOOQ par exemple, a bien fonctionné dans Scala. Un exemple de code jOOQ dans Scala est donné dans le manuel:

 object Test { def main(args: Array[Ssortingng]): 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) } } } 

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