web-dev-qa-db-fra.com

Hibernate et Scala

Je jouais avec Scala et je me demandais si quelqu'un avait déjà utilisé hibernate et mysql comme magasin persistant d'objets scala? Est-ce que cela fonctionne hors de la boîte ou y at-il beaucoup à faire?

37
UberAlex

La plupart du temps, Scala + Hibernate fonctionne assez bien, avec des bosses mineures qui peuvent être facilement surmontées. Par exemple, lorsqu’il s’agit de collections, Hibernate nécessite l’utilisation d’interfaces Java.util. Mais vous pouvez importer scala.collection.jcl.Conversions._ si vous souhaitez utiliser la bibliothèque plus puissante de Scala.

Vous voudrez peut-être consulter Frank Sommers 'post pour plus d'informations.

23
shaolang

Ce n'est certainement pas beaucoup de travail. Un exemple simple hibernate + scala peut être défini en quelques dizaines de lignes. Scala et Java peuvent être mélangés dans le même projet. En particulier, la combinaison hibernate-scala permet de combiner le framework JPA et une couche orm très flexible avec l’élégance de structures immuables et une programmation fonctionnelle fournie par scala. 

Le moyen le plus simple de tester hibernate et scala consiste à utiliser une base de données hsqldb en mémoire via hibernate/jpa. Tout d’abord, définissons le modèle de domaine. Dans ce cas, une classe de scala annotée selon le style d'hibernation, à propos de mes copains.

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
}

Notez que la classe scala est beaucoup plus compacte que la classe Java, car nous n’avons pas besoin du code habituel getter/setter. Maintenant, assurons-nous que les modules jpa et le modèle de base de données sont chargés. Selon la spécification hibernate, ajoutons le fichier de configuration bien connu d'Hibernate: resources/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>

Après avoir défini la configuration de la persistance, passons au fichier scala principal:

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

  }
}

Le code est assez simple. Une fois que JPA EntityManager est créé via la fabrique, le modèle de données est disponible pour insertion, suppression, requête, à l’aide des méthodes définies dans la documentation de hibernate et jpa. 

Cet exemple a été configuré avec sbt. Après avoir récupéré les packages nécessaires et compilé la source, l'exécution du didacticiel produira le journal suivant:

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
16
natbusa
8
Phil

Notez que Scala 2.8, maintenant dans RC5 et sur le point de paraître prochainement, prend en charge les annotations imbriquées. La version a beaucoup d'autres fonctionnalités intéressantes.

3
user369563

J'utilise hiberner avec Scala. Le vrai problème que je devais résoudre était de savoir comment conserver les énumérations en veille prolongée. J'ai mis ma solution de travail sur github

Scala-enumeration-hibernate

Fondamentalement, il faut définir son propre 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)
    }
 }
3
Marek Zebrowski

Il y a des problèmes. Certaines fonctionnalités de JPA exploitant les annotations imbriquées, par exemple, collections, vous avez des problèmes car Scala ne prend pas encore en charge les annotations imbriquées. Cela disparaîtra quand 2.8 sortira.

Voir Blog de Wille Faler pour plus d’informations sur ce sujet, ainsi que sur d’autres incompatibilités.

3
andyczerwonka

Je n'ai pas utilisé Hibernate avec scala directement, mais j'utilise JPA. Hibernate fournit une implémentation JPA, et la manière dont vous définissez les classes persistantes JPA ou Hibernate n’est pas très différente. Je pense donc qu’utiliser Hibernate sans la couche JPA est possible

2
robmv

Jetez un coup d’œil à Version Scala de Play Framework où l’adaptation JPA est complète pour Scala.

0
takacsot