I've been trying to get onto the Scala Bandwagon and have been diligently reading some books that cover core scala well.
However, like every programmer I'm enthusiastic to apply my acquired black arts to my work and justify to myself that this truly is productive.
While trying to apply my skills immediately is admittedly been a bit clunky, I finally managed to get a JPA, Scala piece of work in place. So as usual lets dive into the code.
Note: I'm still a learner, so if anyone has a better approach or feels I'm wrong somewhere or have misunderstood/misinterpreted something, please feel free to shoot.
While trying to apply my skills immediately is admittedly been a bit clunky, I finally managed to get a JPA, Scala piece of work in place. So as usual lets dive into the code.
Note: I'm still a learner, so if anyone has a better approach or feels I'm wrong somewhere or have misunderstood/misinterpreted something, please feel free to shoot.
-
Ensure your Dependencies are right. For this check your JPA & Scala dependencies. If you are self sufficient "good for you", if not; this is what I used :
...
2.9.2 ...5.1.18 2.0.0 1.4 1.0.1.Final 3.3.2.GA 3.4.0.GA 3.3.0.ga 3.4.0.GA 0.9.1.2 ... scala Scala Tools http://scala-tools.org/repo-releases/ true false scala Scala Tools http://scala-tools.org/repo-releases/ true false org.hibernate.javax.persistence hibernate-jpa-2.0-api ${hibernate.jpa2.version} org.hibernate hibernate-core ${hibernate.core} commons-collections commons-collections org.hibernate hibernate-commons-annotations ${hibernate.commons.annotations.version} javax.persistence persistence-api hibernate org.hibernate org.hibernate hibernate-annotations ${hibernate.annotations.version} org.hibernate hibernate-entitymanager ${hibernate.em.version} net.sf.ehcache ehcache mysql mysql-connector-java ${mysql.java.connector.version} org.hsqldb hsqldb ${hypersonic.db.version} test c3p0 c3p0 ${pooling.c3p0.version} javax.validation validation-api 1.0.0.GA compile org.scala-lang scala-library ${scala.version} - Setup your Entity manager and DB connection Pool. I hooked mine to MySQL. Am assuming Connection Pool details not required. Plenty of articles for that. I use Spring with org.springframework.orm.jpa.JpaTransactionManager, com.mchange.v2.c3p0.ComboPooledDataSource, org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.
Note: My dependencies also rely on Spring, but I have omitted those in my POM config sample above for brevity as they are standard Spring dependencies. - In the source folder : src/main/scala. I created two Files:
package com.neurosys.quizapp.domain import javax.persistence.Entity import javax.persistence.OneToMany import javax.persistence.GeneratedValue import scala.annotation.target.field import javax.persistence.Id import javax.persistence.GenerationType import javax.persistence.CascadeType import javax.persistence.FetchType import javax.persistence.OneToOne /** * @author Arjun Dhar, NeuroSystems Technologies Pvt. Ltd. */ @Entity(name="questions") case class Question(text: String) { //def this() = this(null) @(Id @field) @(GeneratedValue @field)(strategy = GenerationType.AUTO) var id:Long = 0L def setId(id:Long) = {this.id = id} def getId:Long = this.id def getText = this.text @OneToOne(optional=false) var correctAnswer:Answer = null def setCorrectAnswer(correctAnswer:Answer) = {this.correctAnswer = correctAnswer} def getCorrectAnswer:Answer = this.correctAnswer @OneToMany(fetch=FetchType.EAGER, mappedBy="question") var answers : java.util.List[Answer]= _ def setAnswers(answers:java.util.List[Answer]) = {this.answers = answers} def getAnswers:java.util.List[Answer] = this.answers }
and
package com.neurosys.quizapp.domain import javax.persistence.Entity import javax.persistence.OneToOne import javax.persistence.GeneratedValue import scala.annotation.target.field import javax.persistence.Id import javax.persistence.GenerationType import javax.persistence.ManyToOne /** * @author Arjun Dhar, NeuroSystems Technologies Pvt. Ltd. */ @Entity(name="answers") case class Answer(text:String, sequence:Int) { //def this() = this(null, "", 0) def this(question:Question, text:String, order:Int) = { this(text, order); this.question = question; } @(Id @field) @(GeneratedValue @field)(strategy = GenerationType.AUTO) var id:Long = 0L def setId(id:Long) = {this.id = id} def getId:Long = this.id @OneToOne(optional=false) var question:Question = null //def setQuestion(question:Question) = this.question = question def getQuestion = this.question //var text:String = null //def setText(text:String) = this.text = text def getText = this.text def getSequence = this.sequence; }
- In Scala, though you can define your members within the constructor arguments itself, Annotating them there does not work -- took a lot of my time. Frankly a bit annoyed it did not work, but I did expect magic!
Example: case class Answer(@OneToOne question:Question, text:String, sequence:Int) will not work. - Notice the style@(GeneratedValue @field)
- I adopted the use of Scala case class; helps in scala taking care of the euqals and hashCode methods which from an OR framework perspective deserves attention.
- You do not have to have your Scala Entity look like a total Java Bean, have the constructor do as much of the hard work and simply implement getters (leave the setters / optional)
- In the Questions entity, the last field called answers has to be a traditional Java Collection. i.e. You cannot use the Scala Trait Seq or List. I would be interested to see the JPA flavour for Scala support these things.
What does the above do?
I wanted to create a simple question bank as a sample exercise.I created a model where one Question can have only one correct answer which the question object is aware of. Also, the answers know which question they belong to.
Interesting points to note:
Very interesting. Thank you for sharing!
ReplyDelete