Using DB2 and myBatis. Some background: I have a trigger on a table that should fire when a row is deleted and insert the row into a history table, and I want the user that deleted the row (not the connection user) to be reflected in a column of this table.
So far, I've written the trigger so that it uses DB2's CLIENT_USERID register to get the user, and also a myBatis interceptor that should set the user whenever a statement is prepared using setClientInfo on the Connection.
The interceptor class is annotated as follows:
#Intercepts({#Signature(
type = StatementHandler.class,
method = "prepare",
args = {Connection.class})})
Interception works, but when I try to call the setClientInfo method on the argument of the intercept method (Connection), it turns out that that method is abstract.
Is there a simpler way to do this or will this work and how do I fix this?
Thanks for looking at this post!
Related
I implemented a query where i mined data from a database but i have to change it so i mine my data from a custom function in my code. I read the documentation and added the annotation import on the configuration. The query throws that error:
Failed to resolve event type, named window or table by name 'path.to.my.class.customfunction'
I don't know the type that my function have to return but i tried Arraylist and Hashmaps with key an integer and value a custom class and didn't work.
My final query want to look like this :
select * from LocationEvent as loc,
***CustomFuntion()*** as product
where loc.id=product.id ;
I kept the structure i used for database connection. I don't know if there is another way to solve this. Thanks.
EDIT: I managed to make call the custom function with that query :
select path.to.class.getProducts() as product from pattern[every timer:interval(3 sec)]
My function right now return an ArrayList and the query returns this:
[Product{ProductID=124,.....,},Product{...}]
So now my problem is that i can't access properties of Product on the query like products.ProductID
If you want to have a custom function in the from-clause you can use the "method:". The docs have this described here: Accessing Non-Relational Data via Method. The Esper runtime then calls your method to get events/rows.
I am facing a weird problem with Spring Boot(2.3.7) + PostgreSQL v12 (row level security) + Hibernate (5.x).
Here are the steps that I am executing
A procedure accepts an input variable and creates temporary table. The variable is then inserted in temporary table.
Spring Advice which executes for all #Service annotation and invokes a procedure with a variable (call it custom_id).
#Transactional attribute is specified on all #Service classes.
PostgreSQL row level security has been enabled on the tables being queried and updated.
Row level security applies filter based on the variable stored (custom_id value) in temporary table.
All update, select, insert operations are executed using custom implementation of JpaRepository (interface based)
This works fine as long as there are only select operation performed on the database. But starts to fail with code having a combination of select and updates. The code simply fails with a message as it is not able to locate the temporary table.
I enabled trace for Spring transaction and found that there are few statements like
No need to create transaction for XXX
While code that performs update operation has statements like
Getting transaction for XXX
After searching for a while, I realised that SimpleJpaRepository has #Transaction with readonly flag set to true. This results in SELECT operation getting executing in transaction less mode.
Procedure
create or replace procedure proc_context(dummy_id uuid) AS $context_var$
declare
begin
create temp table if not exists context_metadata
(
dummy_id uuid
)
on commit drop;
insert into context_metadata values(dummy_id);
end;
$context_var$ LANGUAGE plpgsql;
ERROR
Following error is logged in console
ERROR: relation "context_metadata" does not exist
What I tried
Tried implementing custom transaction manager and explicitly invoking the procedure to set the temporary variable value (Didn't work). Refer below
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
super.prepareSynchronization(status, definition);
if (status.isNewTransaction() || status.isReadOnly() || status.isNewSynchronization()) {
UUID someID = ....;
Query query = entityManager.createNativeQuery("CALL proc_context(?);");
query.setParameter(1, someID);
query.executeUpdate();
}
}
Tried setting #Transactional notation with readonly set to false on all repositories.
What I am looking for?
Unfortunately due to this behaviour, the row-level security implementation is not working in my code. Is there any way to disable read-only transactions using a global property OR provide me with any hint to overcome this problem?
Finally, I could figure out after 2 days of battle. The problem was multi-faceted.
I noticed hibernate.transaction.flush_before_completion property set to true in application.properties file. I had to remove that property.
Developer had written a very messy code to update the entity attributes (Was performing select, then creating new instance, populating attributes and then calling save method). All this ruckus to update one single attribute.
Tested the code and everything worked fine.
We are developing the ADF application, where in we came accross the requirement that we have to log all the operations into the database which user has performed like all the DML operations (Insert, update , delete), this can be achieved by overriding the doDML method of entity impl class, but now one more requirement is there where we have to log the event when user has queried the records i.e DQL.
May I Know which entity impl method is getting called when we queries the record?
or is there any other way to perform audit logging when user queries the record in ADF?
Thanks
You can use this method to intercept querying:
protected void bindParametersForCollection(QueryCollection qc,
java.lang.Object[] params,
java.sql.PreparedStatement stmt)
throws java.sql.SQLException
Please check slide 10, but use this method instead of executeQueryForCollection() if you run JDev 12c
i have a table in mysql which has a data type of timestamp as one of the columns, which gets a default value of CURRENT_TIME upon insertion. and i have another timestamp column that has a default value of CURRENT_TIME upon update. i have these so that timestamp columns will get updated automatically on insertion and update (which works fine).
now i am using cxf, hibernate/jpa, mysql, jackson to build a web service.
i am simply creating a new record and retrieving it right away as below code shows.
Session session = getSession(); // sessionFactory.getCurrentSession();
String accountId = (String)session.save(account);
Account newAccount = (Account)session.load(Account.class, accountId);
logger.info("created timestamp=" + newAccount.getCreatedTimestamp());
after above code is ran, i can see that new record is created in mysql with correct timestamps for createdTimestamp. however, logger.info() line above throws an exception because newAccount.getCreatedTimestamp() returns null. if i remove logger.info() line, i can see that newAccount object is populated with correct values except for createdTimestamp which is null.
what's more odd is that after above code is ran (which is a part of HTTP POST operation), i call a HTTP GET service which just fetches a record that i just inserted by doing
session.get(Account.class, accountId);
and it correctly shows timestamps!
i tried to sleep before session.load() or session.get() thinking that there might be a delay in inserting timestamp, but that didn't do much. is there something special about hibernate session management that does not retrieve columns that mysql generates? what am i missing here? please help.
Your actual save isn't being committed until the session is flushed. Hibernate doesn't actually commit anything to the database until the session is flushed or closed so that if an exception is thrown, a rollback doesn't actually have to touch the physical database, the changes are just not sent. However if Hibernate detects that a query is going to receive stale data, it will automatically flush before running that query.
For example, you add a record to the database and immediately call a SELECT COUNT(*) query. Hibernate will flush the session (committing the record in the process) and then perform the SELECT COUNT(*) query on the now clean session ensuring that you get correct data. Hibernate didn't do this in your case because it saw that you were requesting the same object that you were trying to insert (in the same session) so it just returned you that reference.
If you are letting hibernate manage its sessions (using a session factory or similar) I don't think that you have to explicitly close sessions. I know that I don't, but I'm using Hibernate with Spring, and using the #Transactional annotation which manages the actual Hibernate session. If you want an immediate insert, make your call to save() the last call in the method. Usually, once the method exits, a commit() will be called automatically.
All the load() will be doing is giving you the same instance of Account that you passed into session.save(). Either close or flush the session, then try the load() again, and your value should be set.
I have the following code
resultList = daoResources.jdbcTemplate.query(sql, selectParams, new BeanPropertyRowMapper(resultClass));
SQL when run with the selectParams against database, I get result. The selecting fields name of the sql matches with the fields in the resultClass too. But for above code, I get an empty resultList.
Where could be the problem?
Debugging is your friend in this scenario. I suggest you enable debug logs for jdbc template to see what sql's and bind parameters are sent to database. Below is from the 3.0.x reference doc
All SQL issued by this class is logged at the DEBUG level under the
category corresponding to the fully qualified class name of the
template instance (typically JdbcTemplate, but it may be different if
you are using a custom subclass of the JdbcTemplate class).