I am new to Hibernate, I could see that Hibernate throws StaleObjectStateException while multiple users trying to persist the complete entity. But, Most of the DB updates I have done using HQL update query. Now, I have added an extra condition to the HQL update queries as 'where version = :currentVersion' to identify no other user updated the particular record. It seems to be working fine. But, problem is that I have many number of queries and I also have to synchronize the version number in my java object as same in DB. Is there any simple way to get 'StaleObjectStateException' on HQL query update during multi user updates?
You understood this wrong. Hibernate throws StaleObjectStateException as a wanted behaviour for "while multiple users trying to persist the complete entity". This prevents that the last writer wins and overrides the data from his antecessors. Usually you catch this Exception and show some Error Message to the User like "Someone has changed the Data. Please Retry!". Your HQL query clause is the wrong way and will force you to patch your code even more and more.
Related
So, I am currently trying to use Liquibase inside a java application. For now it works fine, I built myself a little tool, which creates and updates a h2 Database without any problems. The problem arises when I try to use formatted SQL changeSets.
I use a xml MasterChangelog. In this changelog I specify two changeLogs: One XML which contains the Database Structure and creates all needed tables for me, the second is a SQL changeLog containing all my insert statements with all the data.
updating works and the data is put into the database, problem I can't rollback. So I looked it up and learned that I need to put in a rollback statement for every changeset, which I did but it still doesn't work
Example: SOME_TABLE('ID_TABLE1', 'ID_TABLE2', 'someInput')
--changeset my.name:someId
INSERT INTO "PUBLIC"."SOME_TABLE" VALUES('someId', 'someOtherID', 'someInput');
--rollback DELETE FROM SOME_TABLE WHERE ID_TABLE1='someId'
this doesn't work
--changeset my.name:someId
INSERT INTO "PUBLIC"."SOME_TABLE" VALUES('someId', 'someOtherID', 'someInput');
INSERT INTO "PUBLIC"."SOME_TABLE" VALUES('someId', 'differentId', 'someInput');
INSERT INTO "PUBLIC"."SOME_TABLE" VALUES('someId', 'IdFromHell', 'someInput');
--rollback DELETE FROM SOME_TABLE WHERE ID_TABLE1='someId'
or this
I added a semicolon after the rollback, left them away after the inserts, making every insert its own changeset or grouping them together like above, but nothing works. I always get the infamous: "No inverse to liquibase.change.core.RawSQLChange created".
I tried these inside the h2 database and the statements for themselves work fine. I don't get what is wrong, whether using the console or my java logic it doesn't work. Does anybody know what's wrong?
If so, I am thankful for every hint I can get.
I am running java application with multiple threads those will query from oracle database and if condition meets it will update row. But there are high chances that multiple threads gets same status for a row and then multiple thread try to update same row.
Lets say if status is "ACCEPTED" for any row then update it to "PROCESSING" status and then start processing, But processing should be done by only one thread who updated this record.
One approach is I query database and if status is "ACCEPTED" then update record, I need to write synchronized java method, but that will block multi-threading. So I wanted to use sql way for this situation.
Hibernate update method return type is void. So there is no way I can find if row got updated now or it was already updated. Is there any Select for Update or any locking thing in hibernate that can help me in this situation.
You can very well make use of Optimistic Locking through #Version.
Please look at the post below:
Optimistic Locking by concrete (Java) example
I think that your question is related to How to properly handle two threads updating the same row in a database
On top of this I woud say on top of the answer provided by #shankarsh that if you want to use a Query and not the entitymanager or the hibernate session you need to include the version field in your query like this:
update t.columntoUpdate,version = version + 1 from yourEntity where yourcondition and version = :version
This way the update will succeed only for a particular version and all the concurent updates will not update anything.
I explain better my question since from the title it could be not very clear, but I didn't find a way to summarize the problem in few work. Basically I have a web application whose DB have 5 tables. 3 of these are managed using JPA and eclipselink implementation. The other 2 tables are manager directly with SQL using the package java.sql. When I say "managed" I mean just that query, insertion, deletion and updates are performed in two different way.
Now the problem is that I have to monitor the response time of each call to the DB. In order to do this I have a library that use aspects and at runtime I can monitor the execution time of any code snippet. Now the question is, if I want to monitor the response time of a DB request (let's suppose the DB in remote, so the response time will include also network latency, but actually this is fine), what are in the two distinct case described above the instructions whose execution time has to be considered.
I make an example in order to be more clear.
Suppose tha case of using JPA and execute a DB update. I have the following code:
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnit);
EntityManager em=emf.createEntityManager();
EntityToPersist e=new EntityToPersist();
em.persist(e);
Actually it is correct to suppose that only the em.persist(e) instruction connects and make a request to the DB?
The same for what concern using java.sql:
Connection c=dataSource.getConnection();
Statement statement = c.createStatement();
statement.executeUpdate(stm);
statement.close();
c.close();
In this case it is correct to suppose that only the statement.executeUpdate(stm) connect and make a request to the DB?
If it could be useful to know, actually the remote DBMS is mysql.
I try to search on the web, but it is a particular problem and I'm not sure about what to look for in order to find a solution without reading the JPA or java.sql full specification.
Please if you have any question or if there is something that is not clear from my description, don't hesitate to ask me.
Thank you a lot in advance.
In JPA (so also in EcliplseLink) you have to differentiate from SELECT queries (that do not need any transaction) and queries that change the data (DELETE, CREATE, UPDATE: all these need a transacion). When you select data, then it is enough the measure the time of Query.getResultList() (and calls alike). For the other operations (EntityManager.persist() or merge() or remove()) there is a mechanism of flushing, which basically forces the queue of queries (or a single query) from the cache to hit the database. The question is when is the EntityManager flushed: usually on transaction commit or when you call EntityManager.flush(). And here again another question: when is the transaction commit: and the answer is: it depends on your connection setup (if autocommit is true or not), but a very correct setup is with autocommit=false and when you begin and commit your transactions in your code.
When working with statement.executeUpdate(stm) it is enough to measure only such calls.
PS: usually you do not connect directly to any database, as that is done by a pool (even if you work with a DataSource), which simply gives you a already established connection, but that again depends on your setup.
PS2: for EclipseLink probably the most correct way would be to take a look in the source code in order to find when the internal flush is made and to measure that part.
I am a beginner at hibernate and have read up a lot but I'm stuck at this one point.
In my JSF app that I'm implementing hibertate, I have this SQL query that works in my database:
SELECT *
FROM CourseProduct
INNER JOIN Course
ON CourseProduct.number=Course.number
inner join Product
on CourseProduct.product=Product.product;
I am trying to do the same thing with hibernate for my JSF application. So far I came up with:
List results = session.createCriteria(Course.class)
.setFetchMode("product", FetchMode.JOIN)
.setFetchMode("number", FetchMode.JOIN)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
Is this correct or completely wrong? Also how do I access the fields from the results (if I even have to do that, since hibernate populates the classes for me)? It seems like the results I get are only the the Course Table, the value of the primary key in Product, but not the other 2 fields in the table Product.
EDIT
I guess I solved my own problem. It looks as though the above code is correct, I just didn't realize that in order to access the class Product I had to access it from the Set in the Course class! I just used an iterator to get the data I need in the get method for the set of Products in the Course class.
I guess I solved my own problem. It looks as though the above code is correct, I just didn't realize that in order to access the class Product I had to access it from the Set in the Course class! I just used an iterator to get the data I need in the get method for the set of Products in the Course class.
Update: I really solved the problem. I just got rid of hibernate. The sql query works fine, got my data using a perpared Statement and the result set using the regular old way (java.sql.DriverManager).
For some reason the hibernate driver didn't even like using my statement as a native SQL (kept giving me an exception trying to convert an Integer). I googled the problem and they say it's a bug in hibernate!
I'm using the EclipseLink provider to talk to a mysql database. I've noticed that in on area of my application the library is returning query data that doesn't match the DB.
The query is:
#NamedQuery(name = "EmailAddress.findAll", query = "SELECT e FROM EmailAddress e")
This query is correct, I'm certain of that. The code that I'm using to run that query is:
EntityTransaction entr = em.getTransaction();
entr.begin();
emailAddresses = em.createNamedQuery("EmailAddress.findAll").getResultList();
em.close()
I've put a breakpoint on the close so that I can see the contents of the emailAddress list, about 1 time in 3 it the array is populated incorrectly.
A bit more background - I have a table that lists names, clicking on a name pops up a dialogue and allows you to change the name, upon clicking save it closes the dialogue and updates the table (both DB and UI), sometimes the UI is incorrectly updated and the editted name does not update. The update runs code including that above block. The database is correctly updated prior to the code being run, it's just that array is not populated correctly.
Has anybody else had any issues related to this or have any ideas?
Any help much appreciated!
I fixed this by making the cache refresh on every query, so it was something with the cache. As this app is single user and not very big there aren't many DB hits so this is fine for this application.
Difficult to say without seeing the rest of the code, but are you sure that:
Your transactions are not long winded (i.e. you don't open a transaction and keep it open while waiting for the user is doing something). You should open and close transactions around data queries/updates only.
You are calling persist(), merge() and refresh() respectively when you are creating or updating entities.