2009-07-16 18 views
41

Sto per scrivere un'applicazione della riga di comando di Scala che si basa su un database MySQL. Ho cercato in giro per gli ORM e sto avendo problemi a trovarne uno che funzioni bene.Quali ORM funzionano bene con Scala?

Il Lift ORM sembra bello, ma non sono sicuro che possa essere disaccoppiato dall'intero framework web Lift. Anche ActiveObjects sembra OK, ma l'autore dice che potrebbe non funzionare bene con Scala.

Non vengo a Scala da Java, quindi non conosco tutte le opzioni. Qualcuno ha usato un ORM con Scala, e se sì, cosa hai usato e quanto bene ha funzionato?

risposta

34

Ci sono diversi motivi per cui quadri JPA-oriented (Hibernate, per esempio) non rientrano in applicazioni idiomatiche Scala elegantemente:

  • non ci sono annotazioni nidificate come afferma il Scala 2.8 Preview - questo significa che non è possibile utilizzare le annotazioni come metadati mappatura per applicazioni complesse (anche le più semplici usano spesso @JoinTable ->@JoinColumn);
  • le incoerenze tra le serie Scala e Java fanno sì che gli sviluppatori convertano le raccolte; ci sono anche casi in cui è impossibile mappare collezioni Scala ad associazioni senza implementare interfacce complesse del framework sottostante (ad esempio, Hibernate PersistentCollections);
  • alcune funzionalità molto comuni, come la convalida del modello di dominio, richiedono le convenzioni JavaBeans sulle classi persistenti - queste cose non sono del tutto "alla Scala" del fare le cose;
  • naturalmente, i problemi di interoperabilità (come i tipi di dati grezzi oi proxy) introducono un livello completamente nuovo di problemi che non possono essere facilmente girati.

Ci sono più motivi, ne sono sicuro. Ecco perché abbiamo avviato lo Circumflex ORM project. Questo ORM puro alla Scala cerca di eliminare gli incubi dei classici ORM di Java. In particolare, si definiscono le entità in praticamente modo in cui si esegue questa operazione con istruzioni DDL classici:

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] 

Come si può vedere, queste dichiarazioni sono un po 'più dettagliato, di classico JPA POJO.Ma in effetti ci sono diversi concetti riuniti:

  • il DDL preciso per generare schema (è possibile aggiungere facilmente indici, chiavi esterne e altre cose nello stesso modo di DSL);
  • tutte le query possono essere assemblate all'interno di tale "oggetto tabella" anziché essere sparse in DAO; le query stesse sono molto flessibili, è possibile memorizzare oggetti query, predicati, proiezioni, sottoquery e alias di relazione in variabili in modo da poterli riutilizzare e persino eseguire operazioni di aggiornamento in batch da query esistenti (insert-select ad esempio);
  • la navigazione trasparente tra le associazioni (one-to-one, many-to-one, one-to-many e many-to-many-through-intermediate-relation) può essere ottenuta sia da strategie pigre o da appropting fetching; in entrambi i casi le associazioni sono stabilite sulla base delle chiavi esterne delle relazioni sottostanti;
  • convalida è la parte del framework;
  • c'è anche un plugin Maven2 che consente di generare schemi e importare dati iniziali da file in formato XML a portata di mano.

Le uniche cose Circonflesso ORM mancano sono:

  • tasti multi-colonna primaria (anche se è possibile creare multi-colonna chiavi esterne supportate da più colonne vincoli unici, ma è solo per integrità dei dati);
  • documentazione a tutti gli effetti (anche se stiamo lavorando attivamente su di esso);
  • storie di successo di sistemi di produzione da dieci miliardi di dollari che hanno Circumflex ORM come tecnologia di base.

P.S. Spero che questo post non sia considerato una pubblicità. Non è così, davvero - stavo cercando di essere il più obiettivo possibile.

+0

Questo è abbastanza bello: non vedo l'ora di provarlo. –

+3

Ottimo per vedere più attenzione allo spazio ORM in Scala nativa. Un'altra libreria che ho trovato è http://squeryl.org/. Fornisce funzionalità di stile .net Linq alle tue domande. – user127386

9

Ho sperimentato con EclipseLink JPA e le operazioni di base hanno funzionato bene per me. JPA è uno standard Java e ci sono altre implementazioni che possono anche funzionare (OpenJPA, ecc.). Ecco un esempio di ciò che una classe JPA in Scala assomiglia:

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 potrebbe incontrare alcuni problemi di bytecode, che può essere risolto utilizzando 'livello di accesso protected' con i campi . – SkyDan

2

Ecco fondamentalmente lo stesso esempio con @Column annotazione:

/* 
    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

Sono felice di annunciare la prima versione di una nuova libreria ORM per Scala. MapperDao associa le classi di dominio alle tabelle del database. Attualmente supporta mysql, postgresql (il driver oracle sarà presto disponibile), le relazioni one-to-one, many-to-one, one-to-many, many-to-many, le chiavi autogenerate, le transazioni e si integra opzionalmente con la primavera struttura. Permette la libertà nella progettazione delle classi di dominio che non sono influenzate dai dettagli di persistenza, incoraggia l'immutabilità ed è sicuro. La libreria non è basata sulla riflessione, ma piuttosto sui buoni principi di progettazione di Scala e contiene una DSL per interrogare i dati, che ricorda da vicino le query selezionate. Non richiede l'implementazione di equals() o hashCode() metodi che possono essere problematici per le entità persistenti. La mappatura viene eseguita usando il codice Scala di tipo sicuro.

Dettagli e istruzioni per l'uso si possono trovare presso il sito del mapperdao:

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

La libreria è disponibile per il download sul sito di cui sopra e anche come una dipendenza Maven (documentazione contiene dettagli su come usarlo via maven)

Esempi possono essere trovati in:

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

molto breve introduzione della biblioteca tramite codice di esempio:

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)) 

Interrogazione è molto familiare:

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 

incoraggio tutti di utilizzare la libreria e dare un feedback. La documentazione è attualmente piuttosto estesa, con le istruzioni di installazione e utilizzo. Non esitate a commentare ed entrare in contatto con me a kostas dot kougios su googlemail dot com.

Grazie,

Kostantinos Kougios

2

Slick è un partner perfetto per un mondo funzionale. Gli ORM tradizionali non sono perfetti per Scala. Slick si compone bene e usa un DSL che imita le classi della collezione Scala e per le comprensioni.

1

Ovviamente, qualsiasi framework di accesso al database Java funzionerà anche in Scala, con i soliti problemi che è possibile riscontrare, come la conversione delle raccolte, ecc. JOOQ ad esempio, è stato osservato che funziona bene in Scala. Un esempio di codice jOOQ a Scala è dato nel manuale:

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) 
    } 
    } 
} 

Tratto da http://www.jooq.org/doc/2.6/manual/getting-started/jooq-and-scala/

Problemi correlati