on my dao i have two queries. if the first query is successfully committed then second query should run.but if the first query is committed but second query somehow failed to commit/got some exception then the first query which is committed should also be rolled back. how can i do it?
#Repository
public class UpdatePaymentImpl implements UpdatePayment {
#Autowired
SessionFactory sessionFactory;
Session session;
Transaction trans;
#Override
public int updatePayment(#RequestBody UpdateParam updateParam) {
String totalFee=updateParam.getTotalFee();
// float amountPaid=Float.toString(updateParam.getAmountPaid());
String amountPaid=Double.toString(updateParam.getAmountPaid());
//System.out.println(amountPaid);
String depositSlioNo=updateParam.getDepositSlipNo();
String masterId= updateParam.getMasterId();
String advCode=updateParam.getAdvCode();
try{
session=sessionFactory.openSession();
trans=session.beginTransaction();
Query query= session.createQuery
("update CandidateappearagainstadvtcodeEntity cd set cd.paymentstatus='Completed',
cd.amountpaid=:depoFee,cd.challanid=:depositSlip where
cd.studentmasterid=:masterid and cd.advertisementcode=:advCode");
System.out.println(updateParam.getAdvCode());
query.setParameter("depoFee",amountPaid);
query.setParameter("depositSlip",depositSlioNo);
query.setParameter("masterid",masterId);
query.setParameter("advCode",advCode);
int result= query.executeUpdate();
trans.commit();
System.out.println("update successful");
if(result>0){
String masterId1= updateParam.getMasterId();
String advCode1=updateParam.getAdvCode();
Double amountpaid1=updateParam.getAmountPaid();
session = sessionFactory.openSession();
trans = session.beginTransaction();
Query query1 =session.createQuery(" update CandidateappeartoadvtnumberEntity
cnd set cnd.paymentstatus='Completed', cnd.depositedfee=:depofee where
cnd.studentmasterid=:masterid
and cnd.advertisementcode=:advcode");
query1.setParameter("depofee",amountpaid1);
query1.setParameter("masterid",masterId1);
query1.setParameter("advcode",advCode1);
int result1 = query1.executeUpdate();
trans.commit();
System.out.println("updated");
}
return result;
}catch (Exception e){
System.out.println("update error " +e);
trans.rollback();
return 0;
}finally {
session.close();
}
}
}
looks like you creating two different sessions and has separate commit operation.
To reach your goals you have to open one session and one transaction, then execute both queries and only after successful execution do commit.
In that case if any on query execution will fail you won't affect database state. Currently you already commit first query so if your second query will fail the changes from previous query won't be reverted.
Here is an example.
Related
I am using hibernate in my automation testing project, to execute a database 'clean-up routine' that is:
disabling constraints for all tables in the database
removing records by ID's that I stored when creating records used for my automation testing
enabling constraints for all tables in the database
Here is my pseudo code:
private SessionFactory sessionFactory;
private void initialize()
{
try
{
Configuration config = createHibernateConfiguration();
addAnnotatedClassesForClientDB(config);
StandardServiceRegistryBuilder serviceRegistryBuilder = new StandardServiceRegistryBuilder();
serviceRegistryBuilder.applySettings(config.getProperties());
serviceRegistry = serviceRegistryBuilder.build();
sessionFactory = config.buildSessionFactory(serviceRegistry);
}
catch (HibernateException e)
{
logger.error("Problem creating session factory!");
e.printStackTrace();
}
}
public Session openSession()
{
Session session = sessionFactory.openSession();
session.beginTransaction();
return session;
}
public void cleanClientDatabase()
{
Session session = openSession();
try
{
logger.info("Client DB cleaning started...");
String combinedQuery = // her comes my SQL query
Query query = session.createNativeQuery(combinedQuery);
query.executeUpdate();
closeSession(session);
}
catch (Exception e)
{
logger.error("Failed cleaning Client DB! " + e.getClass().getSimpleName());
e.printStackTrace();
session.getTransaction().rollback();
session.close();
}
}
Now from time to time, it sticks at query.executeUpdate(); in cleanClientDatabase() method and will hang there forever, until I manually kill transaction in Microsoft SQL Management studio by PID.
For some reason an exception is never thrown so I can't tell what is the error, I suspect some sort of lock, what can I do to avoid this issue and fix my code?
Thank you.
i write class to fetch data using hibernate query. when i get Session from EntityManager using
Session session=null;
sessionFactory=entityManager.unwrap(SessionFactory.class);
session=(Session) sessionFactory.getCurrentSession();
or
Session session = (Session) entityManager.getDelegate();
and session agin asking cast the session into EntityManager
public class BranchCustomRepositoryImpl implements BranchCustomRepository{
#PersistenceContext
private EntityManager entityManager;
private SessionFactory sessionFactory;
public Branch findByOrgOrgIdAndBranchId(String orgId, String branchId) {
//Session session=null;
//sessionFactory=entityManager.unwrap(SessionFactory.class);
//session=(Session) sessionFactory.getCurrentSession();
Session session = (Session) entityManager.getDelegate();
System.out.println("BranchCustomRepositoryImpl");
Long orgId2=Long.valueOf(orgId);
Long branchId2=Long.valueOf(branchId);
try{
Query query= (Query)((EntityManager) session).createQuery("from Branch b where b.org.orgId=:orgId AND b.branchId=:branchId");
query.setParameter("orgId", orgId2);
query.setParameter("branchId", branchId2);
return (Branch) query.uniqueResult();
}catch(Exception e){
System.out.println("Exception"+e.toString());
}finally{
try {
if(session!=null){
session.close();
System.out.println("session closed");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
it getting error like,
java.lang.IllegalArgumentException: Parameter value [1] did not match expected type [java.lang.Long (n/a)]
if any one know how to use hibernate query in spring data jpa please help me
Since the type of persistent attribute orgId2 is Long, the corresponding
type argument should also be Long while creating the ParameterExpression. And consequently, because type of the ParameterExpression is Long, type of the parameter's value should also be Long as well. So do the following change when you setting query parameters.
Instead of your current lines such as below
query.setParameter("orgId", orgId2);
query.setParameter("branchId", branchId2);
Change it like below
query.setParameter("orgId", Long.valueOf(orgId2));
query.setParameter("branchId", Long.valueOf(branchId2));
First time that I ran into this error I've surrounded my tx.commit() with a if condition but am not sure why I am still receiving this error.
Struts Problem Report
Struts has detected an unhandled exception:
Messages:
Transaction not successfully started
File: org/hibernate/engine/transaction/spi/AbstractTransactionImpl.java
Line number: 200
Stacktraces
org.hibernate.TransactionException: Transaction not successfully started
org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:200)
After a product has been selected by user, in my main function I will call two functions as following.
First function to retrieve the object of selected product.
Second function to check if selected user has the product therefore it returns true if client has the product otherwise returns false;
Function 1
....
Product pro = new Product();
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
try {
pro = (Product) session.get(Product.class, id);
if (!tx.wasCommitted()) {
tx.commit();
}
} catch (Exception e) {
tx.rollback();
e.printStackTrace();
}
} finally {
HibernateUtil.closeSession();
}
.....
Function 2
.....
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
try {
User user = (User) session.get(User.class, id);
if (!tx.wasCommitted()) {
tx.commit();
}
if(client.hasProduct(proId)){
return client.getProduct(proId);
}
return false;
} catch (Exception e) {
tx.rollback(); <<<Error is on this line
e.printStackTrace();
}
} finally {
HibernateUtil.closeSession();
}
....
Take a look at Transaction.isActive() method. You can wrap call to rollback() method with condition, checking whether transaction is still active. And the second, I'd prefer the following code:
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
// do things
tx.commit();
} finally {
if (tx.isActive()) {
try {
tx.rollback();
} catch (Exception e) {
logger.log("Error rolling back transaction", e);
}
}
try {
session.close();
} catch (Exception e) {
logger.log("Error closing session", e);
}
}
Of course, code in the finally section better to wrap into public static method and just call it in every finally.
BTW, why are you doing something outside tranaction? I usually commit after all things get done, to achieve a better consistency and avoid LazyInitializationException.
One possibility is that the exception you are catching in the second functions is from the code after the commit(), so you end up trying to rollback a transaction that is already committed, which is not allowed.
You could try reorganizing your code to make sure that rollback is never called after commit. Maybe even something simple like reducing the scope of the inner try-catch:
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
try {
User user = (User) session.get(User.class, id);
if (!tx.wasCommitted()) {
tx.commit();
}
} catch (Exception e) {
tx.rollback();
e.printStackTrace();
}
if(client.hasProduct(proId)){
return client.getProduct(proId);
}
return false;
} finally {
HibernateUtil.closeSession();
}
The error indicates the transaction wasn't started at the time tried to roll back - and the problem may be that you are trying to wrap a get, which does not alter the db state and does not leave behind garbage that needs to be committed or rolled back. Nothing changes when you perform select *.
In addition to this, you may want to extract this transaction handling into a common method that is independent of the work being done, so you don't have to write this over and over again, that leaves your code open for bugs. Basically, it seems like you are getting DB objects but then intermingling some business logic withing the same method. Perhaps consider doing something like below:
DB Handling Function
public static <T> T getDBObject( Class<T> clazz, Serializable id )
throws SQLException
{
Session session = null;
try
{
session = HibernateUtil.getSession();
return (T)session.get( clazz, id );
}
finally
{
if ( session != null )
{
session.close();
}
}
}
Now that you can pull object of the DB (note that they will be detached, but still valid), you can then perform work on the objects. I many not have captured exactly what you need to check, but it seems like it is something like:
Example Comparison Function
public boolean doesUserHaveProduct(Serializable userId, Serializable productId)
{
try
{
User user = getDBObject(User.class, userId);
Product product = getDBObject( Product.class, productId );
return user.hasProduct( product );
}
catch (SQLException e)
{
e.printStackTrace();
return false;
}
}
My web application used hibernate mysql. I can add records to database without having any issue. But if i going to update latest adding record It will not updating. But if I re-start the server(tomcat) and then try to update It's working.
To update the record following condition should be satisfied.
//Check record aready exist
public boolean idExists(String id) {
Session session = (Session) HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<Officer> list = (List<Officer>) session.createQuery("from Officer as p where p.idno =" + "\'" + id.trim() + "\'").list();
return (list.size() > 0) ;
}
Immediate(return 1) adding records It will returns 0. But one restart the server and update the record It will work. I also verify after adding record it's successfully commit to DB.
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static{
try{
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
}catch(Throwable ex){
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Let me know if something wrong in my code?
Hibernate does not interact with database immediately after transaction or it does at the time of flushing session, it manages and updates its record to increase system performance in its own way, If you want immediate reflection use :
session.flush();
After updating records.
You could try to flush the session. Entities are not immediately persisted into the database.
session.flush();
I think better you use Transactions here.
You put session.biginTranasaction();
Instead do something like,
public boolean idExists(String id) {
Session session = (Session) HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
List<Officer> list = (List<Officer>) session.createQuery("from Officer as p where p.idno =" + "\'" + id.trim() + "\'").list();
tx.commit();
if(session != null){
session.close();
}
return (list.size() > 0) ;
}
On other end you should generate new session and do other stuffs.
public List<ShoworderbybidId> queryTradesByBid(String bid) throws Exception {
Session session=null;
Transaction transaction=null;
List<ShoworderbybidId> orders=new ArrayList<ShoworderbybidId>();
try {
session=HibernateSessionFactory.getSession();
transaction=session.beginTransaction();
Query query=session.createQuery("from Showorderbybid");// In this way, I could query all results from view Showorderbybid
//Query query=session.createQuery("from Showorderbybid where bid = "+bid); //I try to use this code to find out the orders from a view(Showorderbybid) in my database. However, it failed. It said " Unknown column 'ru0001' (bid=ru0001) in 'where clause' "
orders=(List<ShoworderbybidId>)query.list();
transaction.commit();
} catch (Exception e) {
throw e;
}finally{
HibernateSessionFactory.closeSession();
}
return orders;
}
You can use criteria to create conditional query, however you can also use what you had write in your code, i think there should be problem with "bid" column, is it's name is same as in the bean? and give your error trace.