How to log into separate files per thread using EclipseLink - java

Scenario: Multi-threaded application that interacts with a relational database using EclipseLink JPA Implementation
Desired: Having each thread to log SQL activity to a different file
The documentation states that it's possible to use the following property to specify which file the persistence unit should log to:
<property name="eclipselink.logging.file" value="output.log"/>
Also, the documentation states that it's possible to include a thread identifier into the set of logged informations using the following property:
<property name="eclipselink.logging.thread" value="true"/>
Unfortunately, the most one can get from the combination of these two properties is a unique file with logging information of all the threads in mixed order. This will likely force to post-process the file in some way (e.g. grep) to obtain a "log-per-thread".
Is there any way that I'm missing to obtain this? And if so, is it necessarily a programmatic solution?

Related

Whitelist specific query from hibernate slow query logging

I am using below hibernate settings to log slow queries for my application
hibernate.session.events.log.LOG_QUERIES_SLOWER_THAN_MS : <time>
org.hibernate.SQL_SLOW: warn
It is working fine. But I want to whitelist a few queries so that even if they run beyond 'LOG_QUERIES_SLOWER_THAN_MS' will not be logged as a warning. I want to do that as I know there are a few queries which supposed to take a longer time to run and I don't want to generate any alerts for those.
Is there any way I can do that?
I have tried to find any settings I can provide during the query to override the behaviour for that specific query.
Are there any settings and API hibernate provide to achieve it?
There is no way to do that with plain Hibernate. You can just disable the org.hibernate.SQL_SLOW logger temporarily with your logger API by setting the level programatically to e.g. WARN and then reset it again to INFO.

Create a Hibernate schema not automatically, but with SQL script

In my project I use h2 in memory database, and I want it to be created not by Hibernate, but with by a SQL script. Here is my hibernate.properties
I made
hibernate.hbm2ddl.auto=none
none to disable autocreation of database, and added
hibernate.hbm2ddl.import_files=schema.sql,insert-users.sql
schema.sql contains SQL code to create schema, and then to insert-users.sql and it contains the initial data.
The project builds successfully, but when I try to hit database, I get
a Table <tablename> not found exception.
Since Hibernate won't do this for you unless you use create or create-drop hbm2ddl, there are other ways to achieve what you want.
Specialized tools
There are tools that are created specifically for this: Flyway, LiquiBase. These are often configured to be run when the app is deployed and allow you to version DB scheme. They are applicable not only for testing (and mainly - not for testing), but for production as well. They can ensure that the scheme on all your envs is the same. If you use these tools, then it's better to set hbm2ddl to validate.
Spring's support
Less widespread way is to use Spring's support for embedded DBs:
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
Data for testing
If the intention is to create data for testing (not scheme), then it's better to create entities and use your DAO/Repository layer to persist those in tests. This way you don't duplicate mechanisms of persisting data.
Two comments from the Hibernate documentation are relevant here:
This is useful for testing or demoing: by adding INSERT statements for example you can populate your database with a minimal set of data when it is deployed.
and
These statements are only executed if the schema is created ie if hibernate.hbm2ddl.auto is set to create or create-drop.
I'm not too sure that the import functionality will do what you want it to do.

How to track the SQL calls from eclipse-link JPA to DB

I am using eclipse link as a JPA implementation and am connected to a DB running on "jdbc:XXX://localhost:35001/". Is there a way I can track all the sql calls? I am running this inside a java project in eclipse on my local machine.
Thanks
Several options you can try:
You could try using a proxy like P6spy as mentioned by Andreas, or alternative ones like log4jdbc etc. This can be useful in debugging when you are trying to trace calls from multiple clients since the proxy could intercept the calls from them all.
However for your case I would suggest using the built in logging facilities of EclipseLink. In eclipse link you can configure logging of the statements via entries in the persistence XML like shown below:
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
I would suggest that after making the code changes to undeploy the application and stop and restart the application server before rebuilding and then deploying the application again. I have seen more than few instances where the logging does not start with you going through this entire cycle.
The last option would be a SQL trace. Depending on your database backend you might be able to run a profile or trace. SQL-Server would allow you to trace it. You can then view all SQL executed against the database. This is probably overkill in your scenario as it will log all activity unless configured incorrectly.

How to get EntityManager(s) for mulitple persistence units

I am writing a JEE7 application that runs in WebSphere Liberty Profile 8.5.5. We are using JPA (which is implemented via Eclipselink in WLP).
I have multiple persistence units in the same 'persistence.xml' file. I also need to access two of those units in the same class.
I am getting a runtime error when I try to use the second EntityManager:
#PersistenceContext(unitName = "wwer-list")
private EntityManager entityManagerWwerList;
#PersistenceContext(unitName = "main-dashboard")
private EntityManager entityManagerMainDashboard;
E WTRN0062E: An illegal attempt to use multiple resources that have only one-phase capability has occurred within a global transaction.
How do I get rid of this error?
Also, all of the tables I am using are only needed for reading. So how can I specify that I only want read-only access to JPA?
This issue is prompting because one of your datasource configured as (single phase commit) using ConnectionPoolDataSource and other is configured with XADataSource.
If you want to continue with the same datasource configuration, you will have to update your Server configuration to "Acccept Heuristic Hazard".
In the admin console, click the EAR, select the check box "Accept heuristic hazard". Re-start the server.
This link to enable the Last Participant Support may also help.
http://www.ibm.com/support/knowledgecenter/SSAW57_7.0.0/com.ibm.websphere.nd.doc/info/ae/webui_pme/ui/ueac_laoextensionsettings.html
I can't tell for sure without your persistence.xml and server.xml configurations, but it looks like the <dataSource> elements backing your <persistence-unit> configurations are not XA capable.
By default, a <dataSource> should be a javax.sql.XADataSource (and therefore XA capable), however if you are using a JDBC driver that does not provide an XADataSource implementation, Liberty will pick a simpler DataSource implementation (i.e. javax.sql.ConnectionPoolDataSource or plain javax.sql.DataSource).
A global transaction is whenever you issue a UserTransaction.begin() and lasts until you issue a commit() or a rollback(). There are other ways that you can get into a global transaction too.
Since you want read-only access, converting your DataSources to XA would probably be overkill. Instead, try to eliminate the global transactions from the equation. If you can't eliminate the global transactions, you can specify XADataSource in your server.xml in the following way:
<dataSource type="javax.sql.XADataSource" ...>
<jdbcDriver .../>
<properties .../>
</dataSource>

How to set default schema in a Spring/mybatis application with Oracle DB?

Coming from a mysql background, I am able to set the default schema name that I want to use for all my sql queries in the connection url. I now have an Oracle DB that I need to access. I am aware that I cannot specify the schema I want to use in the URL since the user is the schema name being used.
I realize that I can use a line of SQL code:
ALTER SESSION SET CURRENT_SCHEMA=default_schema
The project is using mybatis 2.3.5 as my SQL framework, but I am completely new to mybatis. Is there a simple way to configure mybatis to accomplish this? My application is a Spring 3 application, so I am using the Spring DataSourceTransactionManager to manage my transactions. I would presume that the manager must be made aware of this requirement to ensure that the command is sent whenever creating a new connection.
I've tried searching online, but most of the examples I find all have the schema names included within the sql queries in the SqlMaps, which I find to be bad practice.
In an ideal world, the schema name would be part of the URL such that I can make changes to the schema name for different environments (ex: dev, test, prod, etc) without touching the code (ie: only configured at the JNDI/application server level). I would be happy if I could use a Spring configuration value to set this as well as I could still use a JNDI lookup or a system environment property to retrieve the value.
Can anyone point me in the right direction?
Thanks,
Eric
As far as I know, there is no option in Oracle to change your URL in order to connect to a specific user schema.
1) mybatis: You may set your current schema to a deserved one before you start your operations. You can write your specification in a property file and set your method's arguments from that file. You do not need to change your code to change your schema in that case.
<update id="mySetSchemaMethod" parameterClass="String">
ALTER SESSION SET CURRENT_SCHEMA = ${schemaName}
</update>
2) trigger: If you are using this connection only for this particular java application, you can set a client event trigger so set your CURRENT_SCHEMA. This time, you need to change the trigger in order to manage test/prod changes.
CREATE OR REPLACE TRIGGER Set_Schema_On_Logon
AFTER LOGON
ON MY_SCHEMA
BEGIN
ALTER SESSION SET CURRENT_SCHEMA = MY_TEST_SCHEMA;
END;

Categories