java.lang.RuntimeException: java.lang.ClassNotFoundException: slick.jdbc.DatabaseUrlDataSource
though when running tests locally I have no issue. When extracting my jar, slick is there along with the .class files I would expect. Anyone run into this kind of issue?
Hi, I am nesting two futures to execute sequentially but looks like the second db insertion never occurs.
def addEmployee(entryEmployee: EntryEmployee) = {
val now = LocalDateTime.now()
val newEmployee = Employee(0, now, now, entryEmployee.name, entryEmployee.teamId, entryEmployee.notes)
val linkTeam = tables.db.run(tables.teams.filter(_.id === entryEmployee.teamId).map(_.name).result)
val newEmployeeId = tables.db.run(
(tables.employees returning tables.employees.map(_.id) into ((employee, newId) => employee.copy(id=newId)))
+= newEmployee)
for {
teamName <- linkTeam
nei <- newEmployeeId
} yield {
addEvents(Seq(EntryEvent(Some(nei.id), Some(nei.teamId), None, None, EntryEvent.employeeToTeam(nei.name, teamName.head))))
}
newEmployee
}
with addEvents
as
def addEvents(entryEvents: Seq[EntryEvent]) = {
val now = LocalDateTime.now()
val newEvents = entryEvents.map(e => Event(0, now, e.employeeId, e.teamId, e.projectId, e.companyId, e.notes))
println(s"ADDING NEW EVENT ${newEvents.head}")
Await.result(tables.db.run(tables.events ++= newEvents), Duration.Inf)
newEvents
}
AddEvents
gets called and the print is being printed. But when requesting later the events table, it returns empty
ADDING NEW EVENT
is called, it shows: ADDING NEW EVENT Event(0,2020-08-10T15:22:33.854,Some(1),Some(1),None,None,Employee: Robert Langdon joined team: Team Unassigned)
Event
entity has all it needs to be persisted
Await.result(tables.db.run(tables.events ++= newEvents), Duration.Inf)
even if blocked (I Blocked it purposedly to make sure it is doing something, but I'll remove that later) - Doesn't seem to be persisting the new event
GETTING EVENTS
found z: Vector()
Ah yes sorry I didn't realize the problem was in addEvents
. The problem, here, though, is that you do nothing with the whole for comprehension, which means that you will not know whether it succeeds or failed. My guess is that your call in the await fails. In order to be sure of it, do
(
for [...] yield [...]
).onComplete(println)
if this prints an error, you'll know
Failure(org.h2.jdbc.JdbcSQLSyntaxErrorException: Duplicate column name "TEAM_ID"; SQL statement:
insert into "EVENTS" ("CREATED","EMPLOYEE_ID","TEAM_ID","PROJECT_ID","TEAM_ID","NOTES") values (?,?,?,?,?,?) [42121-200])
Ah nice. Glad it helped! Indeed, as a (very strong) rule of thumb, you should never leave a future unattended. As a matter of fact, if I can suggest something to you, I would make addEmployee
return a Future[Employee]
, and do
for {
teamName <- linkTeam
nei <- newEmployeeId
_ <- addEvents(...) // remove the await in the function and leave it return the future inside
} yield newEmployee
and leave to the callee the responsibility to look inside the future
.transactionnaly
and be sure to keep the database in a clean state. Don't take my word for it though, I didn't look your code closely enough
def addEvents(entryEvents: Seq[EntryEvent]) = {
val now = LocalDateTime.now()
val newEvents = entryEvents.map(e => Event(0, now, e.employeeId, e.teamId, e.projectId, e.companyId, e.notes))
val task = tables.db.run(tables.events ++= newEvents)
(newEvents, task)
}
Question:
Insert into a Table from Raw SQL Select
val rawSql: DBIO[Vector[(String, String)]] = sql"SELECT id, name FROM SomeTable".as[(String, String)]
val myTable :TableQuery[MyClass] // with columns id, name and some other columns
Is there a way to use forceInsert
functions to insert data from select into the tables?
If not, Is there a way to generate a sql string by using forceInsertStatements
?
Something like:
db.run {
myTable.map{ t => (t.id, t.name)}.forceInsert????(rawSql)
}
Thanks for the help.
forceInsertQuery
which seems to this but for inserts, and there are DBIO Actions which apparently let me update values based on a computation. But is there a forceUpdateQuery
or do I indeed use DBIO Actions for this purpose?
case class User
and a Users
table
Shape[FlatShapeLevel, Users, User, Users]
outside of class Users
Users
So, how do I write this line:
implicit def userShape: Shape[FlatShapeLevel, Users, User, Users] = ...
?
Users
table, and so cannot access the column
s within it
override def getPaymentErrorsByBookingIds(bookingIds: Seq[UUID]): DBIO[Seq[(UUID, Seq[PaymentError])]] =
paymentErrors
.filter(b => b.bookingId inSet bookingIds)
.groupBy(_.bookingId)
.map {
case (bookingId, errors) => bookingId -> errors
}
.result
trait PaymentErrorTable {
class PaymentErrors(tag: Tag) extends Table[PaymentError](tag, "payment_error") {
def newIdWhenInserting: UUID = UUID.randomUUID()
def currentWhenInserting = new Timestamp((new Date).getTime)
def id = column[UUID]("id", O.Default(newIdWhenInserting), O.PrimaryKey)
def bookingId = column[UUID]("booking_id")
def paymentMethodId = column[String]("payment_method_id")
def error = column[String]("error")
def amount = column[BigDecimal]("amount")
def currency = column[Currency]("currency")
def createdAt = column[Timestamp]("created_at", O.Default(currentWhenInserting))
def * =
(
id,
bookingId,
paymentMethodId,
error,
amount,
currency,
createdAt
) <> ((PaymentError.apply _).tupled, PaymentError.unapply)
}
protected val paymentErrors = TableQuery[PaymentErrors]
}
No matching Shape found.
Slick does not know how to map the given types.
Possible causes: T in Table[T] does not match your * projection,
you use an unsupported type in a Query (e.g. scala List),
or you forgot to import a driver api into scope.
Required level: slick.lifted.FlatShapeLevel
Source type: (slick.lifted.Rep[java.util.UUID], slick.lifted.Query[JdbcPaymentErrorStorage.this.PaymentErrors,booking.PaymentError,[+A]Seq[A]])
Unpacked type: T
Packed type: G
.map {
Hi everyone, I'm using plainsql slick queries and I'm running into the following issue:
Caused by: org.postgresql.util.PSQLException: ERROR: column "expiry_date" is of type timestamp without time zone but expression is of type character varying
The column in question is of type timestamp
with timezone.
Here's how I build my query:
val query = sqlu"""INSERT INTO "offers"
VALUES (
${c.userId.toInt},
${c.categoryId.toInt},
${new Timestamp(Instant.now.toEpochMilli)},
${new Timestamp(c.expiryDate)},
${c.description},
${c.address},
${c.latitude},
${c.longitude},
${new Timestamp(c.startAt)},
${new Timestamp(c.endAt)},
${c.compensation},
${c.imageUrl},
${c.requirements},
${c.title}
)"""
Case.If(aquery.length>0) Then bquery else cquery
It seems that the following does not work, what is the suggested way to perform different queries based on the length of the previous one?