2009-09-29 21 views
37

Tôi đã từng đùa giỡn với Scala và tôi tự hỏi liệu có ai có kinh nghiệm sử dụng hibernate và mysql như một kho lưu trữ lâu dài cho các đối tượng scala không? Nó hoạt động ra khỏi hộp hay có nhiều việc phải làm?Hibernate và Scala

Trả lời

22

Hầu hết thời gian, Scala + Hibernate hoạt động khá tốt, những va chạm nhỏ có thể được khắc phục dễ dàng. Đối với exmaple, khi giao dịch với các bộ sưu tập, Hibernate yêu cầu sử dụng giao diện java.util. Nhưng bạn có thể nhập scala.collection.jcl.Conversions._ nếu bạn muốn khai thác trên thư viện mạnh mẽ hơn của Scala.

Bạn có thể muốn xem Frank Sommers 'bài đăng để biết thêm thông tin.

+2

_Note: _ Trong scala 2,8 'scala.collection.jcl.Conversions' đã được chuyển cho ' scala.collection.JavaConversions'. Vì vậy, bạn nên sử dụng 'import scala.collection.JavaConversions._' trong scala 2.8+. Tài liệu: http://www.scala-lang.org/api/current/scala/collection/JavaConversions$.html. –

+0

Lưu ý rằng liệt kê là một loại đau với Scala và Hibernate, nhưng chúng có thể thực hiện. Mặc dù nó dễ dàng hơn trong Java. – wmacura

2

Tôi chưa sử dụng Hibernate với scala trực tiếp, nhưng tôi đang sử dụng JPA. Hibernate cung cấp một JPA thực hiện, và cách bạn xác định JPA persistent lớp học hoặc Hibernate những người không phải là nhiều khác nhau, vì vậy tôi nghĩ rằng bằng cách sử dụng Hibernate mà không có lớp JPA là có thể

3

Có vấn đề. Bởi vì một số tính năng của JPA tận dụng chú thích lồng nhau, ví dụ: bộ sưu tập, bạn đang gặp rắc rối vì Scala chưa hỗ trợ chú thích lồng nhau. Điều đó sẽ biến mất khi 2.8 ra mắt.

Xem Wille Faler’s Blog để biết thêm về chủ đề này cộng với các điều kiện không tương thích khác.

3

Lưu ý rằng Scala 2.8, bây giờ trong RC5 và dự kiến ​​sẽ phát hành trong thời gian ngắn, hỗ trợ các chú thích lồng nhau. Bản phát hành có nhiều tính năng thú vị khác nữa.

16

Nó chắc chắn không phải là rất nhiều công việc. Ví dụ scala hibernate + đơn giản có thể được định nghĩa trong vài chục dòng. Scala và Java có thể được trộn lẫn trong cùng một dự án. Đặc biệt, sự kết hợp hibernate-scala làm cho có thể kết hợp khung JPA, và một lớp orm rất linh hoạt với sự tao nhã của các cấu trúc bất biến và lập trình chức năng như được cung cấp bởi scala.

Cách dễ nhất để thử nghiệm với hibernate và scala là sử dụng cơ sở dữ liệu hsqldb trong bộ nhớ thông qua hibernate/jpa. Trước hết, hãy xác định mô hình miền. Trong trường hợp này, một lớp scala được chú thích theo phong cách ngủ đông, về bạn bè của tôi.

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 
} 

Lưu ý cách lớp scala, là nhiều hơn nữa gọn nhẹ hơn so với lớp java, vì chúng ta không cần getter điển hình/setter mã boilerplate. Bây giờ, hãy đảm bảo rằng các mô-đun jpa và mô hình cơ sở dữ liệu được tải. Theo thông số kỹ thuật ngủ đông, hãy thêm các tập tin cấu hình hibernate nổi tiếng: nguồn/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> 

Sau khi xác định cấu hình persistency, hãy chuyển các tập tin scala chính:

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

    } 
} 

Mã này khá đơn giản.Khi JPA EntityManager được tạo thông qua nhà máy, mô hình dữ liệu có sẵn để chèn, xóa, truy vấn, sử dụng các phương thức được định nghĩa trong tài liệu về hibernate và jpa.

Ví dụ này đã được thiết lập bằng sbt. Sau khi truy xuất các gói cần thiết và biên dịch nguồn, chạy hướng dẫn sẽ tạo bản ghi sau:

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

Tôi đang sử dụng ngủ đông với Scala. Vấn đề thực sự mà tôi đã phải giải quyết là làm thế nào để tồn tại Enumerations trong hibernate. Tôi đã đặt giải pháp làm việc của tôi trên github

Scala-enumeration-hibernate

Về cơ bản người ta cần phải xác định loại người dùng riêng

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