is it possible to connect to java jOOQ DB? - jooq

I discovered a new interesting service and I'm trying to understand how it works. Please explain how to connect to my jOOQ database from another program?
MockDataProvider provider = new MyProvider();
MockConnection connection = new MockConnection(provider);
DSLContext create = DSL.using(connection, SQLDialect.H2);
Field<Integer> id = field(name("BOOK", "ID"), SQLDataType.INTEGER);
Field<String> book = field(name("BOOK", "NAME"), SQLDataType.VARCHAR);
So, I create but can I connect to it?
Here I have added your code, Lukas.
try (Statement s = connection.createStatement();
ResultSet rs = s.executeQuery("SELECT ...")
) {
while (rs.next())
System.out.println(rs.getString(1));
}
This example was found here
https://www.jooq.org/doc/3.7/manual/tools/jdbc-mocking/
public class MyProvider implements MockDataProvider {
#Override
public MockResult[] execute(MockExecuteContext ctx) throws SQLException {
// You might need a DSLContext to create org.jooq.Result and org.jooq.Record objects
//DSLContext create = DSL.using(SQLDialect.ORACLE);
DSLContext create = DSL.using(SQLDialect.H2);
MockResult[] mock = new MockResult[1];
// The execute context contains SQL string(s), bind values, and other meta-data
String sql = ctx.sql();
// Dynamic field creation
Field<Integer> id = field(name("AUTHOR", "ID"), SQLDataType.INTEGER);
Field<String> lastName = field(name("AUTHOR", "LAST_NAME"), SQLDataType.VARCHAR);
// Exceptions are propagated through the JDBC and jOOQ APIs
if (sql.toUpperCase().startsWith("DROP")) {
throw new SQLException("Statement not supported: " + sql);
}
// You decide, whether any given statement returns results, and how many
else if (sql.toUpperCase().startsWith("SELECT")) {
// Always return one record
Result<Record2<Integer, String>> result = create.newResult(id, lastName);
result.add(create
.newRecord(id, lastName)
.values(1, "Orwell"));
mock[0] = new MockResult(1, result);
}
// You can detect batch statements easily
else if (ctx.batch()) {
// [...]
}
return mock;
}
}

I'm not sure what lines 3-5 of your example are supposed to do, but if you implement your MockDataProvider and put that into a MockConnection, you just use that like any other JDBC connection, e.g.
try (Statement s = connection.createStatement();
ResultSet rs = s.executeQuery("SELECT ...")
) {
while (rs.next())
System.out.println(rs.getString(1));
}

Related

JOOQ DSL using SqlConnection

I am using AsyncSQLClient to get an async. connection to my database in vertx. Now i am struggling how to use JOOQs DSL. I am trying the following:
client.getConnection(res -> {
if (res.succeeded()) {
SQLConnection connection = res.result();
DSL dsl = DSL.using(connection, SQLDialect.POSTGRES_9_4);
connection.close();
client.close();
} else {
}
});
That is not working because using needs a Connection and not an SQLConnection. Is there any way to use an SQLConnection with JOOQ? Is there any other way to create an async connection for JOOQ?
No you can't use JOOQ with the Vert.x AsyncSQL client.
But someone in the Vert.x community has created a jOOQ CodeGenerator to create vertxified DAOs and POJOs
You could implement (and open source!) a "proxy" for the vert.x SQLConnection type. For instance, if you want to run the following vert.x method:
interface SQLConnection {
SQLConnection queryWithParams(
String sql,
JsonArray params,
Handler<AsyncResult<ResultSet>> resultHandler
);
}
Your proxy would expose a method like this instead:
class jOOQSQLConnection {
final SQLConnection delegate;
<R extends Record> jOOQSQLConnection query(
ResultQuery<R> sql,
Handler<AsyncResult<Result<R>>> resultHandler
) {
wrapInjOOQSQLConnection(
// Extract the SQL string from the jOOQ query
delegate.query(sql.getSQL()),
// Extract the bind variables from the jOOQ query and wrap them in the
// JsonArray type, as requested by vert.x
wrapjOOQParamsInJsonArray(sql.getBindValues()),
// This is a handler that receives a vert.x ResultSet and wraps / transforms
// it into a jOOQ result (which contains the <R> type for type safety)
r -> resultHandler.handle(wrapInjOOQResult(r.result()))
);
}
}
The above probably won't work out of the box, but it gives you an idea of how to wrap things.
using (SqlConnection con = connection.getconnection()){
SqlCommand cmd = new SqlCommand("empreg", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#empid", txtempid.Text);
cmd.Parameters.AddWithValue("#empname", txtempname.Text);
cmd.Parameters.AddWithValue("#salary", txtsalary.Text);
cmd.Parameters.AddWithValue("#tell", txttell.Text);
cmd.Parameters.AddWithValue("#address", txtaddress.Text);
cmd.Parameters.AddWithValue("#blog", txtblog.Text);
cmd.Parameters.AddWithValue("#gender", cmbgender.Text);
cmd.Parameters.AddWithValue("#hiredate", dtpdate.Value);
cmd.Parameters.AddWithValue("#op", op);
int i = cmd.ExecuteNonQuery();
//If i > 0 AND op = "insert"
if (i > 0 && op == "insert"){
MessageBox.Show("1 row is saved sucessfuly ");
submode.readdgv("emp", DGV2);
submode.autoid(txtempid, "emp");
txtempname.Clear();
txtsalary.Clear();
txttell.Clear();
txtaddress.Clear();
txtblog.Clear();
cmbgender.SelectedIndex = -1;
dtpdate.Value = DateTime.Now;
txtempname.Focus();
}
else if (i >= 0 && op == "update"){
MessageBox.Show("1 row is updated sucessfuly ");
submode.readdgv("emp", DGV2);
submode.autoid(txtempid, "emp");
}
else if (i >= 0 && op == "delete"){
MessageBox.Show("1 row is deleted sucessfuly");
submode.readdgv("emp", DGV2);
submode.autoid(txtempid, "emp");
}
else{
MessageBox.Show("process is failed");
submode.readdgv("emp", DGV2);
submode.autoid(txtempid, "emp");
}
}

Access ServiceStack session from ConnectionFilter

I am using SQL Server and database triggers to keep a data-level audit of all changes to the system. This audit includes the userID / name of whomever initiated a change. Ideally I'd like to do something like this in my AppHost.Configure method:
SqlServerDialect.Provider.UseUnicode = true;
var dbFactory = new OrmLiteConnectionFactory(ConnectionString, SqlServerDialect.Provider)
{
ConnectionFilter = (db =>
{
IAuthSession session = this.Request.GetSession();
if (session != null && !session.UserName.IsNullOrEmpty())
{
System.Data.IDbCommand cmd = db.CreateCommand();
cmd.CommandText = "declare #ci varbinary(128); select #ci = CAST(#Username as varbinary(128)); set context_info #ci";
System.Data.IDbDataParameter param = cmd.CreateParameter();
param.ParameterName = "Username";
param.DbType = System.Data.DbType.String;
//param.Value = session.UserName;
param.Value = session.UserAuthId;
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
}
return new ProfiledDbConnection(db, Profiler.Current);
}),
AutoDisposeConnection = true
};
container.Register<IDbConnectionFactory>(dbFactory);
Of course, this doesn't work because this.Request doesn't exist. Is there any way to access the current session from the ConnectionFilter or ExecFilter on an OrmLite connection?
The other approach I had started, doing an override of the Db property of Service, doesn't work any more because I've abstracted some activities into their own interfaced implementations to allow for mocks during testing. Each of these is passed a function that is expected to return the a DB connection. Example:
// Transaction processor
container.Register<ITransactionProcessor>(new MockTransactionProcessor(() => dbFactory.OpenDbConnection()));
So, how can I ensure that any DML executed has the (admittedly database-specific) context information needed for my database audit triggers?
The earlier multi tenant ServiceStack example shows how you can use the Request Context to store per-request items, e.g. you can populate the Request Context from a Global Request filter:
GlobalRequestFilters.Add((req, res, dto) =>
{
var session = req.GetSession();
if (session != null)
RequestContext.Instance.Items.Add(
"UserName", session.UserName);
});
And access it within your Connection Filter:
ConnectionFilter = (db =>
{
var userName = RequestContext.Instance.Items["UserName"] as string;
if (!userName.IsNullOrEmpty()) {
//...
}
}),
Another approach is to use a factory pattern, similar to how ServiceStack creates OrmLite db connections in the first place. Since all user-associated calls are made via the ServiceRunner, I piggy-back off of the session that's managed by ServiceStack.
public class TransactionProcessorFactory : ITransactionProcessorFactory
{
public ITransactionProcessor CreateTransactionProcessor(IDbConnection Db)
{
return new TransactionProcessor(Db);
}
}
public abstract MyBaseService : Service
{
private IDbConnection db;
public override System.Data.IDbConnection Db
{
get
{
if (this.db != null) return db;
this.db = this.TryResolve<IDbConnectionFactory>().OpenDbConnection();
IAuthSession session = this.Request.GetSession();
if (session != null && !session.UserName.IsNullOrEmpty())
{
IDbCommand cmd = db.CreateCommand();
cmd.CommandText = "declare #ci varbinary(128); select #ci = CAST(#Username as varbinary(128)); set context_info #ci";
IDbDataParameter param = cmd.CreateParameter();
param.ParameterName = "Username";
param.DbType = DbType.String;
//param.Value = session.UserName;
param.Value = session.UserAuthId;
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
}
return db;
}
}
private ITransactionProcessor tp = null;
public virtual ITransactionProcessor TransactionProcessor
{
get
{
if (this.tp != null) return tp;
var factory = this.TryResolve<ITransactionProcessorFactory>();
this.tp = factory.CreateTransactionProcessor(this.Db);
return tp;
}
}
}
For the sake of potential future ServiceStack users, another approach would be to use OrmLite's Global Insert/Update filters combined with Mythz's approach above to inject the necessary SQL only when DML actions are made. It isn't 100%, since there may be stored procs or manual SQL, but that's potentially handled via an IDbConnection extension method to manually set desired auditing information.

how to get values from SqlDataReader to forloop execution?

Here I coding for get each and every StudyUID(as string) from database to SqlDataReader,but i need to know how the reader value call to forloop execution.
Get to read each and every StudyUID for execution.Here is the code :.
public void automaticreport()
{
//string autsdyid="";
SqlConnection con = new SqlConnection(constr);
con.Open();
string autoquery = "Select StudyUID From StudyTable Where status='2'";
SqlCommand cmd = new SqlCommand(autoquery, con);
SqlDataReader rdr = cmd.ExecuteReader();
for()
{
//how to call each StudyUId from database through for loop
if (!this.reportchk)
{
Reportnew cf = new Reportnew();
ThreadPool.QueueUserWorkItem((WaitCallback)(o => cf.ReportRetrive(this, autsdyid, true)));
}
else
{
int num = (int)System.Windows.Forms.MessageBox.Show("Reports checking in progress, Please wait sometime and try again later", "OPTICS", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
con.Close();
}
Like #R.T and others have mentioned you can use the Read method on the data reader. Looking at your sample code you might want to refactor it slightly to meet more of the SOLID principles and make sure you're not leaking database connections
Here's an example of code that has been refactored a bit.
public void automaticreport()
{
foreach (var autsdyid in LoadStudyIdentifiers())
{
if (!this.reportchk)
{
Reportnew cf = new Reportnew();
ThreadPool.QueueUserWorkItem((WaitCallback)(o => cf.ReportRetrive(this, autsdyid, true)));
}
else
{
int num = (int)System.Windows.Forms.MessageBox.Show("Reports checking in progress, Please wait sometime and try again later", "OPTICS", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
}
}
private string[] LoadStudyIdentifiers()
{
var results = new List<string>();
// adding a using statement will close the database connection if there are any errors
// avoiding consuming the database connection pool
using (var con = new SqlConnection(constr))
{
conn.Open();
var autoquery = "Select StudyUID From StudyTable Where status='2'";
using (var cmd = new SqlCommand(autoquery, con))
{
SqlDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
results.Add(rdr.GetString(rdr.GetOrdinal("StudyUID")));
}
}
}
return results.ToArray();
}
Note: I wrote this in notepad so there is no guarantee it will compile but should give an indication as to how you could refactor your code.
if (rdr.HasRows)
{
while (rdr.Read())
{
Console.WriteLine(rdr.getString("columnName"));
}
}
You can use something like:
while (reader.Read())
{
string value = reader.getString("columnName");
}
You may use the while loop like this:
while (rdr.Read())
{
string s = rdr.GetString(rdr.GetOrdinal("Column"));
//Apply logic to retrieve here
}

ServiceStack.Ormlite single poco map to many tables

I know that Servicestack.Ormlite is setup to be a 1:1 mapping between poco and database table. I have a situation where I will have groups of tables that are of the same structure and they are created as necessary. I am trying to find a way to be able to do something where I can continue to use the IDbConnection and specify the table name in CRUD operations.
Something like
using(var db = _conn.OpenDbConnection()){
db.SaveAll(objList, "DIFFERENT_TABLE");
}
I was easily able to work around to make creating and deleting the tables. I am hoping that I can use of the ExpressionVisitor or something else to help change the table name before it is executed. One of the requirements of the project is that it be database agnostic, which is why I am trying to not manually write out the SQL.
Solutions
Here are a couple of functions that I ended up creating if anyone out there wants some more examples.
public static List<T> SelectTable<T>(this IDbConnection conn, string tableName) {
var stmt = ModelDefinition<T>.Definition.SqlSelectAllFromTable;
stmt = stmt.Replace(ModelDefinition<T>.Definition.Name, tableName.FmtTable());
return conn.Select<T>(stmt);
}
public static List<T> SelectTableFmt<T>(this IDbConnection conn, string tableName, string sqlFilter,
params object[] filterParams) {
var stmt = conn.GetDialectProvider().ToSelectStatement(typeof (T), sqlFilter, filterParams);
stmt = stmt.Replace(ModelDefinition<T>.Definition.Name, tableName.FmtTable());
return conn.Select<T>(stmt);
}
public static void InsertTable<T>(this IDbConnection conn, T obj, string tablename) {
var stmt = conn.GetDialectProvider().ToInsertRowStatement(null, obj);
stmt = stmt.Replace(obj.GetType().Name, tablename.FmtTable());
conn.ExecuteSql(stmt);
}
public static int SaveAll<T>(this IDbConnection conn, string tablename, IEnumerable<T> objs) {
var saveRows = objs.ToList();
var firstRow = saveRows.FirstOrDefault();
if (Equals(firstRow, default(T))) return 0;
var defaultIdValue = firstRow.GetId().GetType().GetDefaultValue();
var idMap = defaultIdValue != null
? saveRows.Where(x => !defaultIdValue.Equals(x.GetId())).ToSafeDictionary(x => x.GetId())
: saveRows.Where(x => x.GetId() != null).ToSafeDictionary(x => x.GetId());
var existingRowsMap = conn.SelectByIds<T>(tablename, idMap.Keys).ToDictionary(x => x.GetId());
var modelDef = ModelDefinition<T>.Definition;
var dialectProvider = conn.GetDialectProvider();
var rowsAdded = 0;
using (var dbTrans = conn.OpenTransaction()) {
foreach (var obj in saveRows) {
var id = obj.GetId();
if (id != defaultIdValue && existingRowsMap.ContainsKey(id)) {
var updStmt = dialectProvider.ToUpdateRowStatement(obj);
updStmt = updStmt.Replace(obj.GetType().Name, tablename.FmtTable());
conn.ExecuteSql(updStmt);
}
else {
if (modelDef.HasAutoIncrementId) {}
var stmt = dialectProvider.ToInsertRowStatement(null, obj);
stmt = stmt.Replace(obj.GetType().Name, tablename.FmtTable());
conn.ExecuteSql(stmt);
rowsAdded++;
}
}
dbTrans.Commit();
}
return rowsAdded;
}
OrmLite supports specifying the table name for Update and Delete operations. Unfortunately the examples in the readme here have yet to be updated. This is the required format:
UPDATE:
db.UpdateFmt(table: "Person", set: "FirstName = {0}".Fmt("JJ"), where: "LastName = {0}".Fmt("Hendrix"));
DELETE:
db.DeleteFmt(table: "Person", where: "Age = {0}".Fmt(27));
The methods you need can be found here. You should be able to use .Exec to handle reading and insert operations.

Entity Framework 5 - Implementing SQL Server "Execute As User"

I am writing a database application using Visual Studio 2012 with Entity Framework 5 and SQL Server 2008. I would like Entity Framework to impersonate a SQL Server user (i.e. user without a login). I have created a new constructor for the DB context MyDatabaseEntities which includes an argument for the name of the user to impersonate. Here is the code that I've written:
public partial class MyDatabaseEntities
{
private String _impersonateUser = null;
public MyDatabaseEntities(String impersonateUser)
: base("MyConnectionString")
{
_impersonateUser = impersonateUser;
this.Database.Connection.StateChange += Connection_StateChange;
}
void Connection_StateChange(object sender, StateChangeEventArgs e)
{
if (e.CurrentState == ConnectionState.Open && e.OriginalState != ConnectionState.Open)
{
using (var cmd = this.Database.Connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("user", _impersonateUser));
cmd.CommandText = "EXECUTE AS USER = #user";
cmd.ExecuteNonQuery();
}
}
}
I had to add the check...
if (e.CurrentState == ConnectionState.Open && e.OriginalState != ConnectionState.Open)
...because the method Connection_StateChange method seems to execute even when the state hasn't changed. Then problem is that when I run the code twice,
public void RunSimpleQuery()
{
using (MyDatabaseEntities context = new MyDatabaseEntities("UserName"))
{
var result = context.TableName.ToList();
}
}
...Entity Framework throws a SqlException:
A severe error occurred on the current command. The results, if
any, should be discarded.\r\nA severe error occurred on the current
command. The results, if any, should be discarded.
Any ideas?
Update 1
I in my code above, I changed...
cmd.CommandText = "EXECUTE AS USER = #user;";
...to...
cmd.CommandText = "REVERT; EXECUTE AS USER = #user;";
...and I still get the same SqlException error.
The problem is that EF closes connection when it doesn't need it and returns it back to the pool. So when it executes some SQL again it request new connection from the pool where your event may not be initialized. But again I believe that you should try to solve this with manually controlling connection lifetime to have both benefit of connection pooling and be able to meet your requirements.
I know is an old question, but maybe will be useful for someone.
I did in a different way, using your code...
Instead of
Connection_StateChanged event
I create two methods in the same class:
public void ChangeUser(String sUser)
{
if(Database.Connection.State != ConnectionState.Open)
Database.Connection.Open();
using (var cmd = Database.Connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("user", sUser));
cmd.CommandText = "EXECUTE AS USER = #user;";
cmd.ExecuteNonQuery();
}
}
public void Revert()
{
if (Database.Connection.State != ConnectionState.Open)
Database.Connection.Open();
using (var cmd = Database.Connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "REVERT;";
cmd.ExecuteNonQuery();
}
}
I use it before and after execute stored procedure,
using (var db = new MyDatabaseEntities())
{
db.ChangeUser(model.Username);
var result = db.Something();
db.Revert();
return result;
}
It works fine with SPs and it doesn't throw an exception even after many executions. If I could catch an event after command execute, maybe all be encapsulated on MyDatabaseEntities.

Resources