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.
Related
Let's say that there are two models, Model1 and Model2, each model has a set of basic methods that call DB to retrieve or write data. For one Model1 there can exist multiple Model2, when inserting a (Model1, List[Model2]) all this data comes from the same form. The current implementation does the following:
Insert the Model1 instance using Model1's insert method.
When Model1 has been correctly inserted, proceed with inserting the List[Model2] using Model2's insert method.
The issue is that if an issue occurs while inserting one of the Model2, Model1 will remain in DB. A solution would be to catch any exception that anorm throws and undo whatever was executed before by doing the exact opposite of it. But is there a solution already out there that can be used? Something that captures all DB calls that were executed and revert them if needed?
What you're looking for is DB.withTransaction. It works exactly the same as DB.withConnection, except that autocommit is set to false, so that if any exceptions are thrown, the entire transaction will be rolled back.
Example:
case class Model1(id: Long, something: String, children: List[Model2])
case class Model2(id: Long, name: String)
object Model1 {
def create(model: Model1): Option[Model1] = {
DB.withTransaction { implicit c =>
SQL(...).executeInsert().map { id =>
model.copy(
id = id,
children = Model2.create(model.children)
)
}
}
}
}
object Model2 {
def create(models: List[Model2])(implicit c: java.sql.Connection): List[Model2] = {
...
}
}
Note how Model2.create accepts an implicit Connection parameter. This is so that it will use the same Connection as the Model1.create transaction, and be allowed to roll back on failure. I've left out the fine implementation details, as the key is just using withTransaction, and running each query on the same Connection.
I'm trying to create my database (code first) and I want to add some data in it when it's created.
public class InitializerWithData : CreateDatabaseIfNotExists<DatabaseContext>
{
protected override void Seed(DatabaseContext ctx)
{
GroupType gt = new GroupType() { Name = "RNC" };
//save
ctx.GroupType.Add(gt);
ctx.SaveChanges();
}
}
public DatabaseContext()
{
Database.SetInitializer<DatabaseContext>(new InitializerWithData());
Database.CreateIfNotExists();
}
As you can see I wrote my custom initializer but the code inside it is never fired though the database does get created.
So how do I solve this?
When you call Database.CreateIfNotExists(), it doesn't trigger the InitializeDatabase of the initializer. Basically it has separated implementation than the initializer.
If you want the Seed method to be fired. You need to execute a code that causes EF to send a query to the database.
First remove this line.
Database.CreateIfNotExists();
Then just execute a query, the least you could have is something like.
using(var db = new DatabaseContext())
{
db.Set<GroupType>().Any();
}
This code will create the database if it doesn't exist and execute the Seed method.
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
I'm trying to put some of my domain classes into the MongoDB using the mongoDB grails plugin. Some of the classes stays in MySQL. Everything works fine even the saving of domain class instances into the MongoDB (for example in service on controller code). However, If I try to save the instance from the afterUpdate() of certain not-mongoDB class it doesn't work. It doesn't throw any exception or whatever...
My not-mongoDB domain class:
class CarState extends AbstractCarState {
...
def afterUpdate() {
def logItemInstance = new CarStateLogItem(this.properties)
logItemInstance.save(failOnError: true)
}
}
MongoDB domain class:
class CarStateLogItem extends AbstractCarState {
ObjectId id
static mapWith = "mongo"
...
}
The weird thing is that if I run the afterUpdate() code from controller it saves into the MongoDB. Am I something missing? Or why I cannot save the instance?
Thanks for any advice,
Mateo
I think you need to initiate a new transaction in order to save in mongodb. If you notice, the transaction for CarState will be of MySQL. In order to transact with mongodb from the afterUpdate event there has to be a new mongodb transaction. Try this.
def afterUpdate() {
CarStateLogItem.withTransaction{status ->
def logItemInstance = new CarStateLogItem(this.properties)
logItemInstance.save(failOnError: true)
}
}
I'm currently working on a project which is using EF Code First with POCOs. I have 5 POCOs that so far depends on the POCO "User".
The POCO "User" should refer to my already existing MemberShip table "aspnet_Users" (which I map it to in the OnModelCreating method of the DbContext).
The problem is that I want to take advantage of the "Recreate Database If Model changes" feature as Scott Gu shows at: http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx - What the feature basically does is to recreate the database as soon as it sees any changes in my POCOs. What I want it to do is to Recreate the database but to somehow NOT delete the whole Database so that aspnet_Users is still alive. However it seems impossible as it either makes a whole new Database or replaces the current one with..
So my question is: Am I doomed to define my database tables by hand, or can I somehow merge my POCOs into my current database and still take use of the feature without wipeing it all?
As of EF Code First in CTP5, this is not possible. Code First will drop and create your database or it does not touch it at all. I think in your case, you should manually create your full database and then try to come up with an object model that matches the DB.
That said, EF team is actively working on the feature that you are looking for: altering the database instead of recreating it:
Code First Database Evolution (aka Migrations)
I was just able to do this in EF 4.1 with the following considerations:
CodeFirst
DropCreateDatabaseAlways
keeping the same connection string and database name
The database is still deleted and recreated - it has to be to for the schema to reflect your model changes -- but your data remains intact.
Here's how: you read your database into your in-memory POCO objects, and then after the POCO objects have successfully made it into memory, you then let EF drop and recreate the database. Here is an example
public class NorthwindDbContextInitializer : DropCreateDatabaseAlways<NorthindDbContext> {
/// <summary>
/// Connection from which to ead the data from, to insert into the new database.
/// Not the same connection instance as the DbContext, but may have the same connection string.
/// </summary>
DbConnection connection;
Dictionary<Tuple<PropertyInfo,Type>, System.Collections.IEnumerable> map;
public NorthwindDbContextInitializer(DbConnection connection, Dictionary<Tuple<PropertyInfo, Type>, System.Collections.IEnumerable> map = null) {
this.connection = connection;
this.map = map ?? ReadDataIntoMemory();
}
//read data into memory BEFORE database is dropped
Dictionary<Tuple<PropertyInfo, Type>, System.Collections.IEnumerable> ReadDataIntoMemory() {
Dictionary<Tuple<PropertyInfo,Type>, System.Collections.IEnumerable> map = new Dictionary<Tuple<PropertyInfo,Type>,System.Collections.IEnumerable>();
switch (connection.State) {
case System.Data.ConnectionState.Closed:
connection.Open();
break;
}
using (this.connection) {
var metaquery = from p in typeof(NorthindDbContext).GetProperties().Where(p => p.PropertyType.IsGenericType)
let elementType = p.PropertyType.GetGenericArguments()[0]
let dbsetType = typeof(DbSet<>).MakeGenericType(elementType)
where dbsetType.IsAssignableFrom(p.PropertyType)
select new Tuple<PropertyInfo, Type>(p, elementType);
foreach (var tuple in metaquery) {
map.Add(tuple, ExecuteReader(tuple));
}
this.connection.Close();
Database.Delete(this.connection);//call explicitly or else if you let the framework do this implicitly, it will complain the connection is in use.
}
return map;
}
protected override void Seed(NorthindDbContext context) {
foreach (var keyvalue in this.map) {
foreach (var obj in (System.Collections.IEnumerable)keyvalue.Value) {
PropertyInfo p = keyvalue.Key.Item1;
dynamic dbset = p.GetValue(context, null);
dbset.Add(((dynamic)obj));
}
}
context.SaveChanges();
base.Seed(context);
}
System.Collections.IEnumerable ExecuteReader(Tuple<PropertyInfo, Type> tuple) {
DbCommand cmd = this.connection.CreateCommand();
cmd.CommandText = string.Format("select * from [dbo].[{0}]", tuple.Item2.Name);
DbDataReader reader = cmd.ExecuteReader();
using (reader) {
ConstructorInfo ctor = typeof(Test.ObjectReader<>).MakeGenericType(tuple.Item2)
.GetConstructors()[0];
ParameterExpression p = Expression.Parameter(typeof(DbDataReader));
LambdaExpression newlambda = Expression.Lambda(Expression.New(ctor, p), p);
System.Collections.IEnumerable objreader = (System.Collections.IEnumerable)newlambda.Compile().DynamicInvoke(reader);
MethodCallExpression toArray = Expression.Call(typeof(Enumerable),
"ToArray",
new Type[] { tuple.Item2 },
Expression.Constant(objreader));
LambdaExpression lambda = Expression.Lambda(toArray, Expression.Parameter(typeof(IEnumerable<>).MakeGenericType(tuple.Item2)));
var array = (System.Collections.IEnumerable)lambda.Compile().DynamicInvoke(new object[] { objreader });
return array;
}
}
}
This example relies on a ObjectReader class which you can find here if you need it.
I wouldn't bother with the blog articles, read the documentation.
Finally, I would still suggest you always back up your database before running the initialization. (e.g. if the Seed method throws an exception, all your data is in memory, so you risk your data being lost once the program terminates.) A model change isn't exactly an afterthought action anyway, so be sure to back your data up.
One thing you might consider is to use a 'disconnected' foreign key. You can leave the ASPNETDB alone and just reference the user in your DB using the User key (guid). You can access the logged in user as follows:
MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
And then use the User's key as a FK in your DB:
Guid UserId = (Guid) currentUser.ProviderUserKey ;
This approach decouples your DB with the ASPNETDB and associated provider architecturally. However, operationally, the data will of course be loosely connected since the IDs will be in each DB. Note also there will be no referential constraints, whcih may or may not be an issue for you.