Aamir Aamir - 1 month ago 39
Scala Question

Simple Slick Example Scala

I was trying to practice a simple slick example with 1 table created in

Postgres
.It involves 4 files.

this is my
DAO.scala
file

import slick.dbio.Effect.Write
import slick.lifted.{CanBeQueryCondition, Rep, Tag}
import slick.jdbc.PostgresProfile.api._
import slick.sql.FixedSqlAction

import scala.concurrent.Future
import scala.reflect._

trait BaseEntity {
val id: Long
val isDeleted: Boolean
}

abstract class BaseTable[E: ClassTag](tag: Tag, schemaName: Option[String], tableName: String)
extends Table[E](tag, schemaName, tableName) {

val classOfEntity = classTag[E].runtimeClass

val id: Rep[Long] = column[Long]("Id", O.PrimaryKey, O.AutoInc)
val isDeleted: Rep[Boolean] = column[Boolean]("IsDeleted", O.Default(false))
}

trait BaseRepositoryComponent[T <: BaseTable[E], E <: BaseEntity] {
def getById(id: Long): Future[Option[E]]

def getAll: Future[Seq[E]]

def filter[C <: Rep[_]](expr: T => C)(implicit wt: CanBeQueryCondition[C]): Future[Seq[E]]

def save(row: E): Future[E]

def deleteById(id: Long): Future[Int]

def updateById(id: Long, row: E): Future[Int]
}

trait BaseRepositoryQuery[T <: BaseTable[E], E <: BaseEntity] {

val query: slick.jdbc.PostgresProfile.api.type#TableQuery[T]

def getByIdQuery(id: Long): Query[T, E, Seq] = {
query.filter(_.id === id).filter(_.isDeleted === false)
}

def getAllQuery: Query[T, E, Seq] = {
query.filter(_.isDeleted === false)
}

def filterQuery[C <: Rep[_]](expr: T => C)(implicit wt: CanBeQueryCondition[C]): Query[T, E, Seq] = {
query.filter(expr).filter(_.isDeleted === false)
}

def saveQuery(row: E): FixedSqlAction[E, NoStream, Write] = {
query returning query += row
}

def deleteByIdQuery(id: Long): FixedSqlAction[Int, NoStream, Write]={
query.filter(_.id === id).map(_.isDeleted).update(true)
}

def updateByIdQuery(id: Long, row: E): FixedSqlAction[Int, NoStream, Write] = {
query.filter(_.id === id).filter(_.isDeleted === false).update(row)
}

}

abstract class BaseRepository[T <: BaseTable[E], E <: BaseEntity : ClassTag](clazz: TableQuery[T])
extends BaseRepositoryQuery[T, E]
with BaseRepositoryComponent[T, E] {
val clazzTable: TableQuery[T] = clazz
lazy val clazzEntity = classTag[E].runtimeClass
val query: slick.jdbc.PostgresProfile.api.type#TableQuery[T] = clazz
val user = "postgres"
val url = "jdbc:postgresql://localhost:5432/learning"
val password = "admin"
val driver = "org.postgresql.Driver"


val db = Database.forURL(url, user = user, password = password, driver = driver)

def getAll: Future[Seq[E]] = {
db.run(getAllQuery.result)
}

def getById(id: Long): Future[Option[E]] = {
db.run(getByIdQuery(id).result.headOption)
}

def filter[C <: Rep[_]](expr: T => C)(implicit wt: CanBeQueryCondition[C]): Future[Seq[E]] = {
db.run(filterQuery(expr).result)
}

def save(row: E): Future[E] = {
db.run(saveQuery(row))
}

def updateById(id: Long, row: E): Future[Int] = {
db.run(updateByIdQuery(id, row))
}

def deleteById(id: Long): Future[Int] = {
db.run(deleteByIdQuery(id))
}

}


this is my
entities.scala
file

import slick.jdbc.PostgresProfile.api._
import slick.lifted.ProvenShape.proveShapeOf
import slick.lifted.{Rep, Tag}

class EmployeeTable(_tableTag: Tag) extends BaseTable[Employee] (_tableTag, Some("learning"), "Employee") {

def * = (id, firstName, isDeleted) <>(Employee.tupled, Employee.unapply)

def ? = (Rep.Some(id), Rep.Some(firstName), Rep.Some(isDeleted)).shaped.<>({ r => import r._; _1.map(_ => Employee.tupled((_1.get, _2.get, _3.get))) }, (_: Any) => throw new Exception("Inserting into ? projection not supported."))

override val id: Rep[Long] = column[Long]("EmployeeId", O.AutoInc, O.PrimaryKey)
val firstName: Rep[String] = column[String]("FirstName")
override val isDeleted: Rep[Boolean] = column[Boolean]("IsDeleted")
lazy val employeeTable = new TableQuery(tag => new EmployeeTable(tag))

}


case class Employee(id: Long, firstName: String, isDeleted: Boolean) extends BaseEntity


this is my
build.scala
file.

name := "SlickAkka"

version := "1.0"

scalaVersion := "2.12.0"

libraryDependencies ++= Seq(
"com.typesafe.slick" % "slick_2.11" % "3.2.0-M1",
"org.postgresql" % "postgresql" % "9.4.1211"
)


and finally my
EmployeeRepository.scala
file

import slick.lifted.TableQuery
import scala.concurrent.ExecutionContext.Implicits.global
abstract class EmployeeRepository
extends BaseRepository[EmployeeTable, Employee](TableQuery[EmployeeTable]){

def insertItem(row: Employee) = {
super.save(row)
}

}

object ImplEmployeeRepository extends EmployeeRepository

object TestEmp extends App {

val emp = Employee(0L, "aamir", false)

for {
result <- ImplEmployeeRepository.insertItem(emp)
_ = println(result)
} yield result
Thread.sleep(5000)

}


as soon as I run 'TestEmp' object it throws this exception:


Exception in thread "main" java.lang.NoClassDefFoundError: scala/Product$class
at slick.ast.ColumnOption$PrimaryKey$.(ColumnOption.scala:15)
at slick.ast.ColumnOption$PrimaryKey$.(ColumnOption.scala)
at slick.relational.RelationalTableComponent$ColumnOptions$class.$init$(RelationalProfile.scala:110)
at slick.relational.RelationalTableComponent$$anon$2.(RelationalProfile.scala:116)
at slick.relational.RelationalTableComponent$class.$init$(RelationalProfile.scala:116)
at slick.jdbc.PostgresProfile$.(PostgresProfile.scala:245)
at slick.jdbc.PostgresProfile$.(PostgresProfile.scala)
at BaseRepository.(DAO.scala:78)
at EmployeeRepository.(EmployeeRepository.scala:3)
at ImplEmployeeRepository$.(EmployeeRepository.scala:11)
at ImplEmployeeRepository$.(EmployeeRepository.scala)
at TestEmp$.delayedEndpoint$TestEmp$1(EmployeeRepository.scala:18)
at TestEmp$delayedInit$body.apply(EmployeeRepository.scala:13)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App.$anonfun$main$1$adapted(App.scala:76)
at scala.App$$Lambda$5/305808283.apply(Unknown Source)
at scala.collection.immutable.List.foreach(List.scala:378)
at scala.App.main(App.scala:76)
at scala.App.main$(App.scala:74)
at TestEmp$.main(EmployeeRepository.scala:13)
at TestEmp.main(EmployeeRepository.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.ClassNotFoundException: scala.Product$class
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 26 more


I can't figure out what is the issue exactly??

Answer

Your Scala compiler version is 2.12 but your slick version is 2.11.

Change the slick version to 2.12 or Change the Scala compiler version to 2.11

name := "SlickAkka"

version := "1.0"

scalaVersion := "2.12.0"

libraryDependencies ++= Seq(
   "com.typesafe.slick" % "slick_2.11" % "3.2.0-M1", //error is here
  "org.postgresql" % "postgresql" % "9.4.1211"
)

Changed correct build.sbt

name := "SlickAkka"

version := "1.0"

scalaVersion := "2.11.8"

libraryDependencies ++= Seq(
   "com.typesafe.slick" % "slick_2.11" % "3.2.0-M1",
  "org.postgresql" % "postgresql" % "9.4.1211"
)

or

name := "SlickAkka"

version := "1.0"

scalaVersion := "2.11.0"

libraryDependencies ++= Seq(
   "com.typesafe.slick" %% "slick" % "3.2.0-M1", //notice double %%
  "org.postgresql" % "postgresql" % "9.4.1211"
)

or With Scala compiler 2.12

name := "SlickAkka"

version := "1.0"

scalaVersion := "2.12.0"

libraryDependencies ++= Seq(
   "com.typesafe.slick" %% "slick" % "3.2.0-M1",
  "org.postgresql" % "postgresql" % "9.4.1211"
)

or Scala compiler 2.12

name := "SlickAkka"

version := "1.0"

scalaVersion := "2.12.0"

libraryDependencies ++= Seq(
   "com.typesafe.slick" % "slick_2.12" % "3.2.0-M1",
  "org.postgresql" % "postgresql" % "9.4.1211"
)