2009-09-29 7 views
37

Ho giocato con Scala e mi chiedevo se qualcuno avesse avuto esperienza con l'uso di ibernazione e mysql come archivio persistente per oggetti scala? Funziona fuori dagli schemi o c'è molto da fare?Hibernate e Scala

risposta

22

La maggior parte delle volte, Scala + Hibernate funziona abbastanza bene, con urti minori che potrebbero essere facilmente superati. Per exmaple, quando si tratta di collezioni, Hibernate richiede l'uso delle interfacce java.util. Ma potresti importare scala.collection.jcl.Conversions._ se vuoi toccare la libreria più potente di Scala.

Si consiglia di controllare il numero Frank Sommers 'per ulteriori informazioni.

+2

_Nota: _ in Scala 2.8 'scala.collection.jcl.Conversions' è stato spostato a' scala.collection.JavaConversions'. Quindi dovresti usare 'import scala.collection.JavaConversions._' in scala 2.8+. Documenti: http://www.scala-lang.org/api/current/scala/collection/JavaConversions$.html. –

+0

Si noti che le enumerazioni sono un po 'dolorose con Scala e Hibernate, ma sono possibili da implementare. Anche se sorprendentemente è più facile in Java. – wmacura

2

Non ho usato Hibernate con scala direttamente, ma sto usando JPA. Hibernate fornisce un'implementazione JPA e il modo in cui definite le classi persistenti JPA o quelle Hibernate non è molto diverso, quindi penso che usare Hibernate senza il layer JPA sia possibile

3

Ci sono problemi. Poiché alcune funzionalità di JPA sfruttano annotazioni annidate, ad es. collezioni, sei nei guai perché Scala non supporta ancora le annotazioni annidate. Questo andrà via quando 2.8 uscirà.

Vedere Wille Faler’s Blog per ulteriori informazioni su questo argomento e altre incompatibilità.

3

noti che Scala 2.8, ora in RC5 e prevede di rilasciare a breve, supporta le annotazioni nidificate. L'uscita ha anche molte altre interessanti funzionalità.

16

Non è sicuramente molto lavoro. Un semplice esempio di ibernazione + scala può essere definito in poche decine di righe. Scala e Java possono essere mescolati nello stesso progetto. In particolare, la combinazione hibernate-scala rende possibile combinare il framework JPA e uno strato di orm molto flessibile con l'eleganza delle strutture immutabili e la programmazione funzionale fornita da scala.

Il modo più semplice per sperimentare Hibernate e Scala consiste nell'utilizzare un database hsqldb in memoria tramite hibernate/jpa. Innanzitutto, definiamo il modello di dominio. In questo caso, una classe di scala annotata secondo lo stile di ibernazione, sui miei amici.

package nl.busa.jpa 
import javax.persistence._ 

@Entity 
@Table(name = "buddy") 
class Buddy(first: String, last: String) { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    var id: Int = _ 

    var firstName: String = first 
    var lastName: String = last 

    def this() = this (null, null) 

    override def toString = id + " = " + firstName + " " + lastName 
} 

nota come la classe Scala, è molto più compatta rispetto alla classe java, dal momento che non abbiamo bisogno l'/ codice standard setter tipico getter. Ora assicuriamoci che siano caricati i moduli jpa e il modello di database. In base alla specifica ibernazione, aggiungiamo il file di configurazione hibernate ben noto: risorse/META-INF/persistence.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
     version="2.0"> 
    <persistence-unit name="nl.busa.jpa.HibernateJpaScalaTutorial"> 
     <description> 
     Persistence unit for the JPA tutorial of the Hibernate Getting Started Guide 
     </description> 
     <class>nl.busa.jpa.HibernateJpaScalaTutorial</class> 
     <properties> 
      <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/> 
      <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:JpaScala"/> 
      <property name="hibernate.show_sql" value="false"/> 
      <property name="hibernate.hbm2ddl.auto" value="create"/> 
     </properties> 
    </persistence-unit> 
</persistence> 

Dopo aver definito la configurazione persistenza, passiamo il file scala principale:

package nl.busa.jpa 

import javax.persistence.EntityManager 
import javax.persistence.EntityManagerFactory 
import javax.persistence.Persistence 

import scala.collection.JavaConversions._ 

object HibernateJpaScalaTutorial  { 

    var entityManagerFactory: EntityManagerFactory = Persistence.createEntityManagerFactory("nl.busa.jpa.HibernateJpaScalaTutorial") 
    var entityManager: EntityManager = entityManagerFactory.createEntityManager() 

    def main(args : Array[String]) { 

    entityManager.getTransaction().begin() 
    entityManager.persist(new Buddy("Natalino", "Busa")) 
    entityManager.persist(new Buddy("Angelina", "Jolie")) 
    entityManager.persist(new Buddy("Kate", "Moss")) 
    entityManager.getTransaction().commit() 

    entityManager.getTransaction().begin(); 
    val allBuddies = entityManager.createQuery("From Buddy", classOf[Buddy]).getResultList.toList 
    entityManager.getTransaction().commit(); 

    allBuddies foreach println 

    entityManager.close(); 

    } 
} 

Il codice è abbastanza semplice.Una volta creato JPA EntityManager tramite la factory, il modello dati è disponibile per l'inserimento, la cancellazione, la query, utilizzando i metodi definiti nella documentazione di hibernate e jpa.

Questo esempio è stato impostato utilizzando sbt. Dopo aver recuperato i pacchetti necessari, e compilare il sorgente, in esecuzione il tutorial produrrà il seguente registro:

HibernateJpaScalaTutorial:-:1.0.0> run 
[info] Running nl.busa.jpa.HibernateJpaScalaTutorial 
1 = Natalino Busa 
2 = Angelina Jolie 
3 = Kate Moss 
[success] Total time: 4 s, completed Dec 9, 2012 4:18:00 PM 
3

Sto usando Hibernate con Scala. Il vero problema che dovevo risolvere era come mantenere Enumerazioni in ibernazione. Ho messo la mia soluzione di lavoro su github

Scala-enumeration-hibernate

In pratica si ha la necessità di definire proprio UserType

abstract class EnumerationAbstractUserType(val et: Enumeration) extends UserType { 
    .... 
    override def nullSafeGet(resultSet: ResultSet, names: Array[String], session: SessionImplementor, owner: Object): Object = { 
    val value = resultSet.getString(names(0)) 
    if (resultSet.wasNull()) null 
    else et.withName(value) 
    } 

    override def nullSafeSet(statement: PreparedStatement, value: Object, index: Int, session: SessionImplementor): Unit = { 
    if (value == null) { 
     statement.setNull(index, Types.VARCHAR) 
    } else { 
     val en = value.toString 
     statement.setString(index, en) 
    } 
}