Up: Part III

G JPA Code Listings

To conserve space and preserve flow in the main text, we’ve placed full code listings for the JPA chapter in this appendix.

G.1 JPA Library Demo

The full library demo is available under the main Lift Git repository at http://github.com/lift/lift/tree/master/examples/JPADemo/. To illustrate some points, we’ve included selected listings from the project.


G.1.1 Author Entity

Author.scala
package com.foo.jpaweb.model
​
import javax.persistence._
​
/**
  An author is someone who writes books.
*/
@Entity
class Author {
  @Id
  @GeneratedValue(){val strategy = GenerationType.AUTO}
  var id : Long = _
​
  @Column{val unique = true, val nullable = false}
  var name : String = ""
​
  @OneToMany(){val mappedBy = "author", val targetEntity = classOf[Book], 
               val cascade = Array(CascadeType.REMOVE)}
  var books : java.util.Set[Book] = new java.util.HashSet[Book]()
}
​


G.1.2 orm.xml Mapping

orm.xml
<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
        http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
​
  <package>com.foo.jpaweb.model</package>
​
  <entity class="Book">
    <named-query name="findBooksByAuthor">
      <query><![CDATA[from Book b where b.author.id = :id order by b.title]]></query>
    </named-query>
    <named-query name="findBooksByDate">
      <query><![CDATA[from Book b where b.published between :startDate and :endDate]]></query>
    </named-query>
    <named-query name="findBooksByTitle">
      <query><![CDATA[from Book b where lower(b.title) like :title order by b.title]]></query>
    </named-query>
    <named-query name="findAllBooks">
      <query><![CDATA[from Book b order by b.title]]></query>
    </named-query>
  </entity>
​
  <entity class="Author">
    <named-query name="findAllAuthors">
      <query><![CDATA[from Author a order by a.name]]></query>
    </named-query>
  </entity>
​
</entity-mappings>


G.1.3 Enumv Trait

Enumv Trait
package com.foo.jpaweb.model
​
/* adds a valueOf function, assumes name is defined
add optional description */
trait Enumv  {
  
  this: Enumeration =>
​
  private var nameDescriptionMap = scala.collection.mutable.Map[String, String]()
​
  /* store a name and description for forms */
  def Value(name: String, desc: String) : Value = {
    nameDescriptionMap += (name -> desc)
    new Val(name)
  }
  
    /* get description if it exists else name */
  def getDescriptionOrName(ev: this.Value) = {
    try {
      nameDescriptionMap(""+ev)
    } catch {
      case e: NoSuchElementException => ev.toString
    }
  }
​
  /* get name description pair list for forms */
  def getNameDescriptionList =  this.elements.toList.map(v => (v.toString, getDescriptionOrName(v) ) ).toList
​
  /* get the enum given a string */
  def valueOf(str: String) = this.elements.toList.filter(_.toString == str) match {
    case Nil => null
    case x => x.head
  }
}


G.1.4 EnumerationType

EnumvType class
package com.foo.jpaweb.model
​
import java.io.Serializable
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
import java.sql.Types
​
import org.hibernate.HibernateException
import org.hibernate.usertype.UserType
​
/**
 * Helper class to translate enum for hibernate
 */
abstract class EnumvType(val et: Enumeration with Enumv) extends UserType {
  
  val SQL_TYPES = Array({Types.VARCHAR})
​
  override def sqlTypes() = SQL_TYPES
​
  override def returnedClass = classOf[et.Value]
​
  override def equals(x: Object, y: Object): Boolean = {
    return x == y
  }
​
  override def hashCode(x: Object) = x.hashCode
​
  override def nullSafeGet(resultSet: ResultSet, names: Array[String], owner: Object): Object = {
    val value = resultSet.getString(names(0))
    if (resultSet.wasNull()) return null
    else {
      return et.valueOf(value)
    }
  }
  
  override def nullSafeSet(statement: PreparedStatement, value: Object, index: Int): Unit = {
    if (value == null) {
      statement.setNull(index, Types.VARCHAR)
    } else {
      val en = value.toString
      statement.setString(index, en)
    }
  }
​
  override def deepCopy(value: Object): Object = value
​
  override def isMutable() = false
    
  override def disassemble(value: Object) = value.asInstanceOf[Serializable]
​
  override def assemble(cached: Serializable, owner: Object): Serializable = cached
​
  override def replace(original: Object, target: Object, owner: Object) = original
​
}


G.1.5 JPA web.xml

This shows the LiftFilter setup as well as the persistence-context-ref.
JPA web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
​
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
​
<web-app>
<filter>
  <filter-name>LiftFilter</filter-name>
  <display-name>Lift Filter</display-name>
  <description>The Filter that intercepts lift calls</description>
  <filter-class>net.liftweb.http.LiftFilter</filter-class>
  <persistence-context-ref>
    <description>
      Persistence context for the library app
    </description>
    <persistence-context-ref-name>
      persistence/jpaweb
    </persistence-context-ref-name>
    <persistence-unit-name>
      jpaweb
    </persistence-unit-name>
  </persistence-context-ref>
</filter>
        
​
<filter-mapping>
  <filter-name>LiftFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
​
</web-app>
​
Up: Part III

(C) 2012 Lift 2.0 EditionWritten by Derek Chen-Becker, Marius Danciu and Tyler Weir