2009-09-29 9 views
37

Ich habe mit Scala gespielt und ich fragte mich, ob irgendjemand irgendeine Erfahrung mit der Verwendung von Hibernate und mysql als persistenter Speicher für Scala-Objekte hatte? Funktioniert es out of the box oder gibt es viel zu tun?Hibernate und Scala

Antwort

22

Die meiste Zeit, Scala + Hibernate funktioniert ziemlich gut, mit kleinere Unebenheiten, die leicht überwunden werden konnten. Zum Beispiel erfordert Hibernate beim Umgang mit Sammlungen die Verwendung von java.util-Schnittstellen. Sie könnten aber scala.collection.jcl.Conversions._ importieren, wenn Sie auf Scalas leistungsfähigere Bibliothek tippen möchten.

Sie möchten vielleicht Frank Sommers 'Post für weitere Informationen.

+2

_Hinweis definieren setzen: _ In scala 2.8 'scala.collection.jcl.Conversions' zu bewegt wurde' scala.collection.JavaConversions'. Also sollten Sie in scala 2.8+ 'scala.collection.JavaConversions._ importieren 'verwenden. Dokumente: http://www.scala-lang.org/api/current/scala/collection/JavaConversions$.html. –

+0

Beachten Sie, dass Aufzählungen eine Art von Schmerzen mit Scala und Hibernate sind, aber sie können implementiert werden. Obwohl es in Java überraschend einfacher ist. – wmacura

2

Ich habe nicht Hibernate mit Scala direkt verwendet, aber ich verwende JPA. Hibernate bietet eine JPA-Implementierung, und die Art, wie Sie JPA persistente Klassen oder Hibernate definieren, ist nicht viel anders, so denke ich, Hibernate ohne die JPA-Ebene ist möglich

3

Es gibt Probleme. Weil einige Merkmale von JPA verschachtelte Annotationen nutzen, z. Sammlungen, Sie sind in Schwierigkeiten, weil Scala verschachtelte Annotationen noch nicht unterstützt. Das wird verschwinden, wenn 2.8 herauskommt.

Weitere Informationen zu diesem Thema sowie weitere Inkompatibilitäten finden Sie unter Wille Faler’s Blog.

3

Beachten Sie, dass Scala 2.8, jetzt in RC5 und kurz, unterstützt Anmerkungen verschachtelte freizugeben erwartet. Das Release hat noch viele andere coole Features.

16

Es ist definitiv nicht viel Arbeit. Ein einfaches Hibernate + Scala-Beispiel kann in einigen Dutzend Zeilen definiert werden. Scala und Java können im selben Projekt gemischt werden. Insbesondere ermöglicht die Hibernate-Scala-Kombination die Kombination des JPA-Frameworks und einer sehr flexiblen Orm-Ebene mit der Eleganz von unveränderlichen Strukturen und funktionaler Programmierung, wie sie von scala bereitgestellt wird.

Der einfachste Weg zum Experimentieren mit Hibernate und Scala ist die Verwendung einer In-Memory-Hsqldb-Datenbank über Hibernate/Jpa. Zunächst definieren wir das Domänenmodell. In diesem Fall eine Scala-Klasse, die nach dem Hibernate-Stil annotiert ist, über meine Buddies.

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 
} 

Hinweis, wie die scala Klasse ist wesentlich kompakter als die Java-Klasse, da wir den typischen Getter/Setter Standardcode nicht brauchen. Stellen wir nun sicher, dass die jpa-Module und das Datenbankmodell geladen sind. Gemäß der Hibernate-Spezifikation, lassen Sie sich die bekannte Hibernate-Konfigurationsdatei hinzufügen: Ressourcen/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> 

Nach der persistency Konfiguration definieren, lassen Sie sich auf der Haupt scala-Datei verschieben:

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

    } 
} 

Der Code ist recht einfach.Sobald der JPA EntityManager über die Factory erstellt wurde, steht das Datenmodell zum Einfügen, Löschen und Abfragen zur Verfügung, wobei die in der Dokumentation von Hibernate und jpa definierten Methoden verwendet werden.

Dieses Beispiel wurde mit sbt eingerichtet. Nachdem die notwendigen Pakete abrufen und die Quelle kompilierte, wird das Tutorial läuft produziert das folgende Protokoll:

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

ich mit Scala wintern verwenden. Das eigentliche Problem, das ich lösen musste, war, wie man Enumerationen im Winterschlaf persistiert. Ich habe meine Arbeitslösung auf Github

Scala-enumeration-hibernate

Grundsätzlich muss man eigene 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) 
    } 
}