Spring + Hibernate Transaction -- Native SQL rollback failure - sql

I recently came across this problem -- my transactional method (marked as #Transactional) failed to do the rollback when I use native SQL. If I instead use Hibernate API to save an entity, it did roll back!
Background
I have a class Employee() and I have a table tbl_employee. I want to use native SQL to insert rows to tbl_employee, and each insertion will insert 500 rows at maximum. For example, if I have 600 employees to insert, I will create two SQL insert queries (one for the first 500 and the other for the next 100). My insert method looks like this (to make it simple, I only consider insertion of (500,1000) rows):
#Transactional
public void insert(List<Employee> list) throws RuntimeException{
Dao dao = new Dao();
String sql1 = buildSQL (list.subList(0,500));//the first 500. buildSQL is a simple method which build an insert query for the list
String sql2 = buiildSQL (list.subList(500,list.size()));//the remaining
dao.executeSQL(sql1);//dao performs the sql query to the database
dao.executeSQL(sql2);
}
And here is the spring configuration. I use HibernateTransactionManager.
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="mySessionFactory"/>
</property>
</bean>
My Dao() class performs my sql to the database and if there is an exception during insertion, I will throw a RuntimeException.
The problem
I tried to insert 501 employees to an empty table. The first 500 have unique ids and the last one has the same id as the first one. Therefore when I insert the last one, there will be a "DUPLICATE PRIMARY KEY" error. I expect that the previous insert() method will rollback -- No rows should be inserted to the table. However, I noticed that the first 500 got inserted to the database!
I then tried to use Hibernate API. My insert method becomes:
#Transactional
public void insert(List<Employee> list) throws RuntimeException{
Dao dao = new Dao();
for (Employee employee: list)
dao.save(employee);
}
And it actually did what I expect! No rows are inserted to the database once there is an exception.
My questions
I wonder if spring/hibernate support transaction management for native SQL.
The rollback works if I directly "save" an entity using Hibernate.The reason why I want to use native sql is that I actually need to insert employees to different tables based on, say, the insertion datetime. (e.g the new emloyees this year will be inserted to tbl_employee_2015).Therefore it's easier to map to different tables using native SQL. Is there any other elegant way to handle mapping to different tables?
I am assuming that one sql for multiple row insertion is very efficient. Therefore I want to insert 500 rows by one sql. I don't want to do Hibernate save one by one in a loop. Is this assumption correct?
Thank you so much for your attention!

Related

Instead of Insert Trigger to prevent from duplicate record in my database

Actually my issue is that,
I have an Azure time trigger function that hitting an API on a daily basis and fetching data from that API and mapping that data through my model classes and inserting that data into my application database.
So there are so many duplicate records in the database so how can prevent that duplicate records to be entered in my database using INstead Of Insert trigger.
As much as I know Instead of Insert trigger use Views for working.

Hibernate + DB2 trigger - SQLCODE:-746

I have DB2 database with some legacy triggers and I am moving from jdbc to Hibernate. My problem is, that I am stucked up with error thrown by DB2 while storing data to DB through Hibernate.
The error -746 says:
If a table is being modified (by INSERT, DELETE, UPDATE, or MERGE),
the table can not be accessed by the lower level nesting SQL
statement.
If any table is being accessed by a SELECT statement, no table can be
modified (by INSERT, DELETE, UPDATE, or MERGE) in any lower level
nesting SQL statement.
In my case I am trying to save entity (which is owned by another already entity saved in this transaction), but there is before-insert trigger in DB, which checks constraint (like "is this instance the only one that has flag set to true?"). But while the attempt to execute this trigger, error is thrown.
I already had similar error while saving another entity with another trigger and I did it like store the problematic entity by JDBC, load it by hibernate and save the rest of entities. But this approach seems to me a bit cumbersome. Is there a way how to resolve this problem? And why exactly is this not working by Hibernate whereas by JDBC is? In both cases it is in one transaction. I tried to flush the data before storing the problematic entity, but did not help.

SQL stored procedure failing in large database

I have a particular SQL file in which i copy all contents from on table in a database to another table in another database.
The traditional INSERT statements are used to perform the same operation. However this table has 8.5 Million records and it fails. The queries succeed with a smaller database.
Also in when i run the select * query for that particular table the SQL query express shows out of memory exception.
In particular there is one table that has some many records. So this table alone i want to copy from the old Db to the new Db.
What are alternate ways to achieve this?
Is there any quick work around by which we can avoid this exception and make the queries succeed?
Let me put it this way. Why would this operation fail when there are a lot of records?
I don't know if this counts as "traditional INSERT", but have you tried "INSERT INTO"?
http://www.w3schools.com/sql/sql_select_into.asp

nhibernate audit trigger error

I'm using triggers on my sql database to capture change information for a table, it seems to be having a problem with nhibernate though.
The table has a few columns and primary keys and triggers on it. The triggers look like this
CREATE TRIGGER [dbo].[tr_Instrument_update] ON [dbo].[Instrument] FOR UPDATE AS
BEGIN
INSERT [MyAudit].[audit].[Instrument]
SELECT 'Updated', i.*
FROM inserted
INNER JOIN [MyAudit].[dbo].[Instrument] i ON inserted.[InstrumentID] = i.[InstrumentID]
END
Basically on every change we copy the row into the audit table. I have tested and if I modify the data directly through sql management studio triggers function correctly and I get data written to the audit table, however if i update through my app I get the following:
NHibernate.StaleObjectStateException
was unhandled by user code
Message=Row was updated or deleted by
another transaction (or unsaved-value
mapping was incorrect)
I assume this is because the trigger updates another table in another database, is there anyway to make nhibernate ignore this as the change will not affect any of its data, in our mappings we have no reference to this audit data.
Figured out that the trigger was causing Nhibernate to do two identical update calls for some reason. The solution was to SET NOCOUNT ON inside the trigger. Still not sure though why nhibernate makes two updates!

Sql Server 2005 - Insert Update Trigger - Get updated, insert row

I want to create a table trigger for insert and update. How can I get the values of the current record that is inserted/updated?
within the trigger, you can use a table called 'inserted' to access the values of the new records and the new version of the updated records. Similarly, the table called 'deleted' allows you to access deleted records and the original versions of updated records.
using function 'update' on column ( if you wanna check the fact of update) or retrieving rows from table 'inserted'
While triggers can be used for this, I'd be very careful about deciding to implement them. They are an absolute bear to debug, and can lead to a lack of maintainability.
if you need to do cascading updates (i.e. altering table A in turn changes table B), I would either use a stored procedure (which can be tested and debugged more easily than a trigger), or if you're fortunate enough to be using an ORM (Entity framework, NHibernate, etc.) perform this function within your model or repository.