Lift-mapper - inserting items to database - scala

I am trying to add item to H2 database. My code is:
class Test extends LongKeyedMapper[Test] with IdPK {
def getSingleton = Test
object name extends MappedString(this, 100)
}
and Test.create.name("some_name").id(2).save, but I always get java.lang.Exception: Do not have permissions to set this field. What can I do wrong? Connection is of course open and I have permission to data from database.

IdPK extends MappedLongIndex which is not writable by default, that's why it restricts you from setting the field. Usually you would let the DB generate an PK ID automatically for you via autoincrement field (postgres, mysql), trigger + sequence (oracle), etc. So in most common scenarios you don't need to set this field. To be able to still set it add an override like this on your field:
override def writePermission_? = true

Related

How to model an enum of String based static Ids in Scala?

let's say I have a reference data table roles filled with all roles that a user might be granted. The rows are quite stable, meaning that it's uncommon that someone adds a new role to the table. Additionally there's a users table and a join-table users_roles. In fact, the roles table is just required to grant a user some predefined roles by adding a record to users_roles.
The roles table is quite simple:
CREATE TABLE IF NOT EXISTS admin.roles (
id CHAR(16) PRIMARY KEY,
description VARCHAR(256) NOT NULL
);
The following example describes a role:
INSERT INTO admin.roles VALUES('CS_AGENT', 'A customer service agent');
Obviously, I need the possible id values somewhere in my code. This is a set of Strings, but I'd like to prevent magic Strings and make this more type safe.
As far as I understand, there are several options:
create a symbol for each role id
create a new type RoleId that extends String and declare vals
In order to define the set of role ids, these are my options:
use an Enumeration
use a sealed trait/sealed object and derive case objects from it
I'm using JOOQ for my persistence layer, and it would be nice if I could use the type safe RoleId in my queries without manually converting it to String and vice versa.
What would be the best solution for this ?
I am not quite sure I get all of your problem, but would not something like this be the solution?
/** Represents a RoleId from the roles table. */
sealed trait RoleId {
def name: String
def description: String
override final def toString: String = name
}
object RoleId {
case object CS_AGENT extends RoleId {
override val name = "CS_AGENT"
override val description = "A customer service agent"
}
// Define all other roles...
/** All roles */
val allRoles: Set[RoleId] = Set(
CS_AGENT,
// All other roles...
)
/** Returns an RoleId given its name, if the name is not found this will return a None. */
def fromString(name: String): Option[RoleId] = name.toUpperCase match {
case "CS_AGENT" => Some(CS_AGENT)
// All other cases..
case _ => None
}
}
This is completely typesafe and if you need to go to/from a String there are the toString and fromString methods.
The only (big) downside of this approach is a lot of boilerplate code which is easy to screw up - creating a new RoleId but not adding it to the Set, typo in the name or in the case, etc.
An alternative to fixing this is to make this file autogenerated by SBT from some kind of config (even reading the SQL table if reachable in the build environment), for that part this answer of mine to another question may help.

How to store override method in a variable in Scala

Here is My Code Snippet
package SimpleDruidOperation
import java.sql.{Connection, Driver, DriverManager, SQLException, Statement}
class ConnectionEstablishment {
var conn:Connection=_
var dr:Driver=_
def connEstablishment() =
{
try {
dr = new com.mysql.jdbc.Driver()
DriverManager.registerDriver(dr)
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/deven","root","root")
if(conn!=null)
println("!!Database Connected Succesfully!!!")
else
println("!!Check your Database Connection !!")
}
catch
{
case e:SQLException=>println("Exception is "+e.getMessage)
}
finally
{
conn.close()
}
}
}
class InsertintoDatabase extends ConnectionEstablishment {
var stmt:Statement=_
// override def connEstablishment():co = super.connEstablishment()
val conn:Connection=connEstablishment()//it is not going to override
def insertintoDatabase(): Unit =
{
println("Checking Conection Establishment")
try {
stmt = conn1.createStatement()
var sql = "insert into emp (eid,ename,eadd,emob) values (101,'Mohit','Pune',9156369938) "
var i = stmt.executeUpdate(sql)
if (i > 0)
println(i + "Value Inserted Successfully into Databaes")
else
println("!!Not Inserted Check something is going wrong!!")
}
catch
{
case e:SQLException=>println("Exception is "+e.getMessage)
}
finally
{
println("Closing Connection Establishment "+conn1.close())
println("CLosing Statement Connection "+conn1.close())
}
}
}
How to store override method in a variable in Scala
Here in my first class ConnectionEstablishment this class is to make connection and second class is for insert into database but the problem is I am unable to override the connEstablisment method because if I want override it then I am unable to establish a connection for insert
because I need it, so that i can call statement stmt=conn,createStatement().
How can I do it?
The problem here is that you have created a class hierarchy when you actually need two separate classes. The ConnectionEstablishment class represents a database connection and the InsertintoDatabase class represents an operation on that database, and there is no natural hierarchy between them.
Class hierarchies should have an "is a" relationship: If D inherits from C then it should make sense to say that a D is a C. So it makes sense for Circle to inherit from Shape because a circle is a shape. It does not make sense for a database operation to inherit from a database connection because a database operation is not a database connection.
A database operation needs a database connection, and this is a containment relationship, not a hierarchy.
So you should have a ConnectionEstablishment class that creates and manages the database connection, and an InsertintoDatabase class that takes a ConnectionEstablishment instance and uses it to insert items into the database.
With this arrangement you can create different subclasses of ConnectionEstablishment that connect to the database in different ways, and the InsertintoDatabase class will work with any of those subclasses. Likewise you can create new classes that use the database connection, such as DeleteFromDatabase, without having to inherit from the existing InsertintoDatabase class.

How to fetch data from ListColumn[String] in Phantom using contains condition

I have a Cassandra table Department with columns name_list extends ListColumn[String] and id extends StringColumn with PartitionKey.
I want to fetch id where the requested name is present in name_list.
I tried using in operator select(_.id).where(name in name_list) but it is not working.
Another query I tried select(_.id).where(_.name_list contains name) but it is also not working for me.
def getByName(name: String) = {
select(_.id, _.name_list).where(_.name_list contains name)
}
Is there any way to solve this!!
You can use the SetColumn as the type for you column then you will be able to use the contains method. Use this
name_list extends SetColumn[String]
then this will work fine
def getByName(name: String) = {
select(_.id, _.name_list).where(_.name_list contains name)
}
Thanks

Mapper's toForm method does nothing on submit?

I have a very simple snippet to add a new row to the books table in the database:
def add = Book.toForm(Full("Add"), { _.save })
Calling this snippet in my template generates a form just fine, and submitting the form gives me a post request, but nothing happens, it never tries to talk to the database, no errors or exceptions occur:
09:03:53.631 [865021464#qtp-2111575312-18] INFO net.liftweb.util.TimeHelpers - Service request (POST) /books/ returned 200, took 531 Milliseconds
I am not sure if my model's save method is just not being called, or if the save method is not working. Based on examples in the book "Lift in Action", I am under the impression that the default Mapper save method should just work, and that is what I am using right now. My model class is simply:
class Book extends LongKeyedMapper[Book] with IdPK {
def getSingleton = Book
object name extends MappedString(this, 100)
}
object Book extends Book with LongKeyedMetaMapper[Book] {
override def dbTableName = "books"
}
Am I missing something in my model, or does this appear to be correct? If this should work, how do I debug it not working?
Forms don't work if you don't have a session (so you need cookies enabled). The session maps the form name to a function on the server. Unfortunately, lift doesn't log an error when the form's handler function isn't found.

row specific class

How do I create a Zend_Db_Table which returns a different class for each row.?
Example
UserTable has id,name and type
Type contains class names (admin,client,etc...)
The classes admin, client are all subclasses of user
If I call fetch I need to get a admin or client object depending on the corresponding value in the db.
class Your_Db_Table_Row extends Zend_Db_Table_Row_Abstract
{
}
class Your_Db_Table extends Zend_Db_Table_Abstract
{
protected $_rowClass = "Your_Db_Table_Row";
}
or
new Your_Db_Table(array("rowClass" => "Your_Db_Table_Row");
So whenever you get a rowset from your table subclass, the rows included in it will be your custom class.
Edit
To get a custom row based on a value, I would say extend the Zend_Db_Table_Rowset_Abstract class instead and override this method:
getRow(int $position, [bool $seek = false])
You'll also need to override the current method and perhaps some of the other SeekableIterator implemetations which actually creates a row class based on the _rowClass property. You might be able to set the _rowClass before current is called based on your data's row type.
You could instantiate a specific class in current and return it based on the type parameter.
Have you though about maybe just using composition instead? Say just passing in data to a new class if it's an admin type or something?