Set Hibernate Session to Read Only for Whole Application - java

I know you can set a session to create "read only" objects by calling setDefaultReadOnly on the session. However, I'm trying to accomplish this for the whole application so that I don't have to set the session to read only every time I interact with it.
Also just to clarify, setting the session to read only doesn't set the connection to read only, it simply disables auto commit and dirty checking for the objects created by the session. This is exactly what I'm after.
Ideally I'm trying to accomplish this in Grails, however, if anyone knows how to do this in Hibernate in general I should be able to port that over to Grails.

It's possible in grails since 2.3.0 version. See here

Related

Read Only Database Connection with Hibernate

Is it possible to use Hibernate and connect to a database with a read only connection? I will be working on a project that will require connecting to an existing database, pulling data from it, and doing some complex data manipulation in the application. Throughout all of this I can`t change anything in the database, hence the read only connection requirement.
My first thought was to pull the data from the database using Hibernate so that I can have ready made Java objects represent the data, however, I can`t seem to find any information on how to force Hibernate to use a read only database connection ... I have a feeling this might actually be impossible, but I want to find out from others before I pursue other ideas.
I don't have enough reputation to comment, apparently :(
But responding to your comment about the cases where Hibernate may still write back to the DB, you could manually detach the object from your persistence context, after which Hibernate would cease caring about the state of the object & whether its been modified.
You can use: Session.setDefaultReadOnly( true );
http://docs.jboss.org/hibernate/orm/3.5/reference/en-US/html/readonly.html#readonly-api-loaddefault
To be bullet-proof safe against anything you do in the application, you need to assign read-only permissions to the DB user that Hibernate is configured to use. This has to be done on the database side. Otherwise, if you rely only on the configuration on the application side, you can always make a mistake (forget to detach the entities, forget to set the session to read-only mode etc.).

Switching between embedded Databases in Java with JPA

Im currently working my way towards JPA 2.0 and I start of liking how easy it is to maintain persistent data.
What I'm currently trying to accomplish is using JPA in a basic desktop application. The application should allow me to open embedded databases which are on my file system. I chose H2 databases for now, but I can really live switching to JavaDB or anything else.
What Im trying to accomplish is, that one can open the database file without previously define a persistence-unit in the persistence.xml file.
I can easily define a unit and persist objects, but it needs to be configured first.
I want to write some sort of database browser which allows opening without preconfiguration and recompiling.
http://www.objectdb.com/java/jpa/start/connection
I saw that ObjectDB allows access for this type of PersistenceFactory creation, but I was not able to transfer this example to other databases.
Am I totally wrong with the way I approach this probblem? Is JPA not designed with on-the-fly database access?
Thank you for your help,
Johannes
Not part of the JPA standard. Some implementations may offer their own API to do it. For example with DataNucleus if you go to this page http://www.datanucleus.org/products/accessplatform_3_0/jpa/persistence_unit.html at the end you can create dynamic persistence-units (and hence EMFs), and that implementation obviously allows persistence to the widest range of datastores you'll get anywhere
You can pass a Map of properties to createEntityManagerFactory() call that defines the database connection info, etc. The property names are the same as in the persistence.xml. I assume most JPA providers support this, EclipseLink does.
You will still need to define the set of classes for the database and map them.
If you do not have any classes either, than you could look into EclipseLink's dynamic support,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Dynamic
If you want to make a database browser accessing different databases, you can't use a PU/Entity Manager (imo).
You'll need a dialogue asking a user for the IP/Port of the database, the username/password, the database name to access, and the type of database.
Then all you need to do is create a socket, send requests over the socket, and parse the response into a view.
Since both the request and the response are database specific, the user has to select the proper database driver.

how to check if a sessionId is valid in a servlet (java)

I am maintaining a map of sessionid(s) and HttpSession Objects in my web app. I use an HttpSessionListener to populate or remove a session from the map. When my web server crashes and goes down and comes back up, i need a way to check if the sessionid being submitted is valid or not. Obviously, when the app comes back online, the Map is empty, therefore all session id's are invalid, but I just want some way to check the incoming sessionid, if possible, at all..
thanks
You can keep those in DB in some table. This way it will not suffer by the crash. And by the way, servers serializes the session to the disk, if you want them too.
One suggestion is to serialize your Map to disk and reload when the Web server starts up. The strategy to backup your Map to disk depends on your requirement, you could write to disk each time you add/update the map or in regular intervals. It is fairly easy to write your session data to disk, this is something that is often done for achieving redundancy and load balancing scenarios.
Why on earth are you maintaining the sessions yourself? The servlet container is supposed to do that for you. I haven't seen your code, maybe you have a good reason for doing what you're doing, but I get the feeling that you just don't understand the servlet API, and are trying to re-implement it yourself.
Also, you might be interested in this: Tomcat has a feature where it persists the sessions, which means that the session state survives a server restart. (Turn this off when updating the application, since there might be mismatches between different versions of classes.)

Spring and Hibernate, Lazy initiation problem

Hey I am developing an desktop application using Spring and Hibernate, and I have a problem with lazy initiation. I looked in the web and every solution is related to the open session in view pattern, but I can't use this pattern. I've also tried to get the sessionfactory from the HibernateTemplate, but it returns to me a disconnected session.
Does anyone know other solution?
I would suggest that you basically have two solutions:
Make arrangements to keep a Hibernate session open when you access a lazy-initialized object or collection. That means you're going to have to carefully mark your transaction boundaries in your code, a la the "open session in view" pattern. Spring makes this possible, but in a desktop application it won't be as straightforward as a web application where the transaction boundaries are a little more obvious.
Turn off all the lazy-initialization for your persisted objects in Hibernate.
Option 2 could lead to a lot of unnecessary database access, and option 1 means you have to seriously study your workflow and use cases.
Hope that helps!
One option is to call Hibernate.initialize() on the entities or collections to force initialize them. You'd want to do this before you return the data back to your view. I would consider this carefully, since it's going to generate a lot of SQL statements back to the database.
You may want to look into using "fetch" in your HQL queries or configuration the fetch mode to "eager" in your mappings (I believe it's FetchMode.EAGER in JPA or lazy="false" in hbm.xml).
#Jose: Don't manage the Session in your own ThreadLocal. Use SessionFactory.getCurrentSession() and configure Hibernate to use the "thread" SessionContext.
I had a very similar problem, and as I was not able to find any really appropriate solution to it. I came up with my own one combining a lot of different approaches found on the web and posted them to my blog.
Sorry, that I don't put it in all here, but it is to much work to do it over and over again in all the forums I found people having this or a similar problem
Remote Lazy Loading with Hibernate and Spring

How to maintain Hibernate cache consistency running two Java applications?

Our design has one jvm that is a jboss/webapp (read/write) that is used to maintain the data via hibernate (using jpa) to the db. The model has 10-15 persistent classes with 3-5 levels of depth in the relationships.
We then have a separate jvm that is the server using this data. As it is running continuously we just have one long db session (read only).
There is currently no intra-jvm cache involved - so we manually signal one jvm from the other.
Now when the webapp changes some data, it signals the server to reload the changed data. What we have found is that we need to tell hibernate to purge the data and then reload it. Just doing a fetch/merge with the db does not do the job - mainly in respect of the objects several layers down the hierarchy.
Any thoughts on whether there is anything fundamentally wrong with this design or if anyone is doing this and has had better luck with working with hibernate on the reloads.
Thanks,
Chris
A Hibernate session loads all data it reads from the DB into what they call the first-level cache. Once a row is loaded from the DB, any subsequent fetches for a row with the same PK will return the data from this cache. Furthermore, Hibernate gaurentees reference equality for objects with the same PK in a single Session.
From what I understand, your read-only server application never closes its Hibernate session. So when the DB gets updated by the read-write application, the Session on read-only server is unaware of the change. Effectively, your read-only application is loading an in-memory copy of the database and using that copy, which gets stale in due course.
The simplest and best course of action I can suggest is to close and open Sessions as needed. This sidesteps the whole problem. Hibernate Sessions are intended to be a window for a short-lived interaction with the DB. I agree that there is a performance gain by not reloading the object-graph again and again; but you need to measure it and convince yourself that it is worth the pains.
Another option is to close and reopen the Session periodically. This ensures that the read-only application works with data not older than a given time interval. But there definitely is a window where the read-only application works with stale data (although the design guarantees that it gets the up-to-date data eventually). This might be permissible in many applications - you need to evaluate your situation.
The third option is to use a second level cache implementation, and use short-lived Sessions. There are various caching packages that work with Hibernate with relative merits and demerits.
Chris, I'm a little confused about your circumstances. If I understand correctly, you have a both a web app (read/write) a standalone application (read-only?) using Hibernate to access a shared database. The changes you make with the web app aren't visible to the standalone app. Is that right?
If so, have you considered using a different second-level cache implementation? I'm wondering if you might be able to use a clustered cache that is shared by both the web application and the standalone application. I believe that SwarmCache, which is integrated with Hibernate, will allow this, but I haven't tried it myself.
In general, though, you should know that the contents of a given cache will never be aware of activity by another application (that's why I suggest having both apps share a cache). Good luck!
From my point of view, you should change your underline Hibernate cache to that one, which supports clustered mode. It could be a JBoss Cache or a Swarm Cache. The first one has a better support of data synchronization (replication and invalidation) and also supports JTA.
Then you will able to configure cache synchronization between webapp and server. Also look at isolation level if you will use JBoss Cache. I believe you should use READ_COMMITTED mode if you want to get new data on a server from the same session.
The most used practice is to have a Container-Managed Entity Manager so that two or more applications in the same container (ie Glassfish, Tomcat, Websphere) can share the same caches.
But if you don't use an Application container, because you use Play! for instance, then I would build some webservices in the primary Application to read/write consistently in the cache.
I think using stale data is an open door for disaster. Just like Singletons become Multitons, read-only applications are often a write sometimes.
Belt and braces :)

Categories

Resources