Issue in updating records in Hibernate - java

Hi I am using Hibernate to update the records in a table. And I'm inserting same records in another table. It is in a loop, but I am getting exception as lock wait timeout exception when I am updating records. Please could anybody resolve this problem? Thanks in advance!
try {
SalesInventoryDAO dao = new SalesInventoryDAO();
sess = HibernateUtil.getSessionFactory().openSession();
Transaction tx = ses.beginTransaction();
GoodsRecievedForm item = (GoodsRecievedForm) form;
GoodsRecieved bk = new GoodsRecieved();
bk.setGoodsId(item.getGoodsId());
InventoryOrder order = (InventoryOrder) sess.get(InventoryOrder.class, item.getOrderNo());
bk.setOrderNo(order);
// if (order.getQuotation().getQuotationNo() != null) {
// bk.setQuotation(order.getQuotation().getQuotationNo());
// } else {
// bk.setQuotation(null);
// }
java.util.Date temp = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(item.getRecievedDate());
java.sql.Date temp1 = new java.sql.Date(temp.getTime());
bk.setRecievedDate(temp1);
bk.setOrderQty(order.getTotalqty());
bk.setReceivedPersonName(item.getReceivedPersonName());
bk.setReceivedQty(item.getReceivedQty());
bk.setConditionOfMaterial(item.getConditionOfMaterial());
UserEntity msg;
HttpSession session = request.getSession(false);
msg = (UserEntity) session.getAttribute("user");
bk.setAddedBy(msg);
bk.setAddedDate(new Date());
int[] item1111 = item.getGoodsDetails();
String[] productre = item.getGoodsDetailsName();
float proqty[] = item.getGoodsDetailsQty();
float price[] = item.getGoodsDetailsPrice();
float receivedqty[] = item.getReceivedquantity();
GoodsReceivedDetails mb;
Set<GoodsReceivedDetails> purDetails = new HashSet();
for (int i = 0; i < productre.length; i++) {
mb = new GoodsReceivedDetails();
mb.setGoodsDetailsName(productre[i]);
mb.setGoodsDetailsQty(proqty[i]);
mb.setGoodsDetailsPrice(price[i]);
mb.setReceivedquantity(receivedqty[i]);
//System.out.println("productre" + productre[i]);
int id3 = item1111[i];
//System.out.println("id3id3id3id3" + id3);
// int id3 = Integer.parseInt(productre[i]);
Item idf = (Item) sess.get(Item.class, id3);
float qty = (idf.getItemStock() + mb.getReceivedquantity());
// mb.setItemId(idf);
// mb.setItemId(idf);
dao.updateitem(qty, idf);
//dao.updateitem(idf);
mb.setGoodsId(bk);
sess.save(mb);
purDetails.add(mb);
}
bk.setGoodsDetails(purDetails);
sess.save(bk);
tx.commit;
//System.out.println("comming");
// List ls = gdao.getOrderItems(order.getOrderId());
// for (Iterator it = ls.iterator(); it.hasNext();) {
// InventoryOrderDetails inv = (InventoryOrderDetails) it.next();
// gdao.updateitem(inv.getItemId().getItemStock() + bk.getReceivedQty(), inv.getItemId());
// }
} catch (Exception e) {
e.printStackTrace();
} finally {
sess.close();
}
This is my dao code..
public void updateitem(float stock, Item itm) {
Session ses = HibernateUtil.getSessionFactory().openSession();
////System.out.println("itmitmitm" + itm.getItemId());
Transaction tx = ses.beginTransaction();
Query qry = ses.createQuery("UPDATE Item set itemStock='" + stock + "' where itemId='" + itm.getItemId() + "'");
qry.executeUpdate();
ses.close();
tx.commit();
}

You have initialized a the transaction by sess.beginTransaction(); in the beginning and before even committing the transaction, you've trying to re-initialize the transaction. This will lead to memory leaks as the previous transactions hasn't been committed. So, before you begin another transaction, commit the previous one.
And here are some suggestions:
‘Lock wait timeout’ occurs typically when a transaction is waiting on
row(s) of data to update which is already been locked by some other
transaction.
Most of the times, the problem lies on the database
side. The possible causes may be a inappropriate table design, large
amount of data, constraints etc.
Please check out this for more details.

Commit transaction before opening new one
Transaction currentTx = sess.beginTransaction();
..
currentTx.commit();
..
currentTx = sess.beginTransaction();
EDIT:
In dao you opening new transaction instead of use previous one.. you should read some tutorials about transaction management in java/hibernate.

Related

using JPA, method is taking a 60 sec

I am working with JPA, my web application is taking 60 sec to execute this method, I want to execute it faster how to achive ?
public boolean evaluateStudentTestPaper (long testPostID, long studentID, long howManyTimeWroteExam) {
Gson uday = new Gson();
Logger custLogger = Logger.getLogger("StudentDao.java");
// custLogger.info("evaluateTestPaper test paper for testPostID: " +
// testPostID);
long subjectID = 0;
// checking in table
EntityManagerFactory EMF = EntityManagerFactoryProvider.get();
EntityManager em = EMF.createEntityManager();
List<StudentExamResponse> studentExamResponses = null;
try {
studentExamResponses = em
.createQuery(
"SELECT o FROM StudentExamResponse o where o.studentId=:studentId And o.testPostID=:testPostID and o.howManyTimeWroteExam=:howManyTimeWroteExam")
.setParameter("studentId", studentID).setParameter("testPostID", testPostID)
.setParameter("howManyTimeWroteExam", howManyTimeWroteExam).getResultList();
System.out.println("studentExamResponses--------------------------------------------------"
+ uday.toJson(studentExamResponses) + "---------------------------------------");
} catch (Exception e) {
custLogger.info("exception at getting student details:" + e.toString());
studentExamResponses = null;
}
int studentExamResponseSize = studentExamResponses.size();
if (AppConstants.SHOWLOGS.equalsIgnoreCase("true")) {
custLogger.info("student questions list:" + studentExamResponseSize);
}
// Get all questions based on student id and test post id
List<ExamPaperRequest> examPaperRequestList = new ArrayList<ExamPaperRequest>();
List<Questions> questionsList = new ArrayList<Questions>();
// StudentExamResponse [] studentExamResponsesArgs =
// (StudentExamResponse[]) studentExamResponses.toArray();
// custLogger.info("Total questions to be evaluated: " +
// examPaperRequestList.size());
List<StudentTestResults> studentTestResultsList = new ArrayList<StudentTestResults>();
StudentTestResults studentTestResults = null;
StudentResults studentResults = null;
String subjectnames = "", subjectMarks = "";
int count = 0;
boolean lastIndex = false;
if (studentExamResponses != null && studentExamResponseSize > 0) {
// studentExamResponses.forEach(studentExamResponses->{
for (StudentExamResponse o : studentExamResponses.stream().parallel()) {
// 900 lines of coade inside which includes getting data from database Queries
}
}
As #Nikos Paraskevopoulos mentioned, it should probably be the ~900 * N database iterations inside that for loop.
I'd say to avoid DB iterations as much as you can, specially inside a loop like that.
You can try to elaborate your current StudentExamResponse sql to englobe more clauses - those you're using inside your for mainly, which could even diminish the amount of items you iterate upon.
My guess would be your select query is taking time.
If possible, set query timeout to less than 60 seconds & confirm this.
Ways of setting query timeout can be found out there - How to set the timeout period on a JPA EntityManager query
If this is because of query, then you may need to work to make select query optimal.

Hibernate insert into Database new records only

I am trying to write some object into the database, I wrote the following code which is working fine but the problem is that because I am using a while loop, hibernate is treating every object as a new record, which causing the database to be filled with already existed value
My question is, which annotation or technique that I can use to only write the new records (new object's value) into the database, without writing the same object again incase it was written before (Insert only if not exists)
Here is my code
public class Parser {
public static void logParser() throws IOException {
// Creating the configuration object
Configuration cfg = new Configuration();
cfg.configure("hibernate.cfg.xml");
// Ccreating the session factory object
SessionFactory factory = cfg.buildSessionFactory();
String fileName = "example.txt";
File logfile = new File("fileName");
Scanner scanner = new Scanner(new File(fileName), "UTF-8");
while (scanner.hasNext()) {
String s = scanner.nextLine();
if (s.startsWith("Start")) {
String[] logArray = s.split("\\|");
System.out.println(Arrays.toString(logArray));
// here is the session object
Session session = factory.openSession();
// transaction
Transaction t = session.beginTransaction();
// here is where the object is being written into the DB
NetGroup ng = new NetGroup();
ng.setNetGroup(logArray[2]);
session.persist(ng);
session.saveOrUpdate(ng);
t.commit();
session.close();
System.out.println("Successfully created an object and wrote its values into database ");
System.out.println();
}
}
scanner.close();
System.out.println("Successfully updated the Data Base");
}
}
Your issue is happened because in each loop you create a new entity and persist it, then you commit and close the session, so when begin a new transaction in second loop there is no reference between the already persisted entity and second one, so new entity will be created.
You need to re find your entity then update it if existed, else create new one and persist it.
That code will fix your issue
public class Parser {
public static void logParser() throws IOException {
// Creating the configuration object
Configuration cfg = new Configuration();
cfg.configure("hibernate.cfg.xml");
// Ccreating the session factory object
SessionFactory factory = cfg.buildSessionFactory();
String logFileName = "example.txt";
File logfile = new File("fileName");
Scanner scanner = new Scanner(new File(fileName), "UTF-8");
// here is the session object
Session session = factory.openSession();
// transaction
Transaction t = session.beginTransaction();
while (scanner.hasNext()) {
String s = scanner.nextLine();
if (s.startsWith("Start")) {
String[] logArray = s.split("\\|");
System.out.println(Arrays.toString(logArray));
Query query = session.createQuery("FROM " + getTableName() + " Where your condition "); // use unique filed
List<NetGroup> list = query.list();
if(list.size()==0){
NetGroup ng =new NetGroup();
}else{
ng =list.get(0);
}
ng.setNetGroup(logArray[2]);
session.saveOrUpdate(ng);
System.out.println("Successfully created an object and wrote its values into database ");
System.out.println();
}
}
session.close();
t.commit();
scanner.close();
System.out.println("Successfully updated the Data Base");
}
}
Make sure put valid condition instead of "your condition"
I think you can use the primary key concept there to remove the duplicacy of rows and use the saveOrUpdate method.
If we work with hibernate API there should be one PK in the class.
session.saveOrUpdate(ng);
That above method check the record on the basis of primary key, if PK does not exists in the DB then it fire the insert query if exists then it update the same record rather than inserting new one.
public class NetGroup
{
private int primaryKeyId;
public int getprimaryKeyId() {
return primaryKeyId;
}
public void setprimaryKeyId(int primaryKeyId) {
this.primaryKeyId = primaryKeyId;
}
}

How to implement a Sign in function by using Gigya API in JAVA?

I am trying to delete the accounts from Gigya DB, so we can reuse them to test our login function through Gigya. It seems the UID required for deletion come from login, so how am I suppose to do it in Java?
As mentioned by Ilan, firstly you'll need to include the Gigya Java SDK.
You can then look up the UID using either the Identity Access or Identity Query Tool within Gigya console and use the follow code to delete the account:
// delete user record
GSRequest deleteAccountRequest = new GSRequest(apiKey, secretKey, "accounts.deleteAccount");
//deleteAccountRequest.setAPIDomain("eu1.gigya.com"); // enable this if you're using the EU data centre
deleteAccountRequest.setUseHTTPS(true);
deleteAccountRequest.setParam("UID", uid);
GSResponse deleteAccountResponse = deleteAccountRequest.send();
if(deleteAccountResponse.getErrorCode()==0)
{
}
else
{
System.out.println("deleteAccountResponse failure: " + deleteAccountResponse.getLog());
}
Alternatively, if you want to delete users in batch, you can run a search using accounts.search and delete all the users within the results set:
int limit = 100;
String query = "select UID from accounts where ... " + limit; // add your query here i.e. email = 'someone#example.com'
String cursorId = "";
int objectsCount = limit;
GSRequest searchRequest;
ArrayList<String> uidList = new ArrayList<String>();
// send request
do
{
// check if we have an open cursor
if(cursorId.length() > 0)
{
// run next request in cursor
// set up request
searchRequest = new GSRequest(apiKey, secretKey, "accounts.search");
//searchRequest.setAPIDomain("eu1.gigya.com");
//searchRequest.setUseHTTPS(true);
// set timeout
searchRequest.setParam("timeout", 60000);
// set cursor id
searchRequest.setParam("cursorId", cursorId);
} else {
// run new request and open cursor
// set up request
searchRequest = new GSRequest(apiKey, secretKey, "accounts.search");
//searchRequest.setAPIDomain("eu1.gigya.com");
//searchRequest.setUseHTTPS(true);
// set timeout
searchRequest.setParam("timeout", 60000);
// set query
searchRequest.setParam("query", query);
// open cursor
searchRequest.setParam("openCursor", true);
}
GSResponse searchResponse = searchRequest.send();
if(searchResponse.getErrorCode()==0)
{
GSArray uids = new GSArray();
uids = searchResponse.getArray("results", uids);
for(int i=0; i<uids.length(); i++)
{
String uid;
try {
// retrieve uid and add to list of uids
uid = uids.getObject(i).getString("UID");
uidList.add(uid);
} catch (GSKeyNotFoundException e) {
}
}
cursorId = searchResponse.getString("nextCursorId", "");
objectsCount = searchResponse.getInt("objectsCount", 0);
}
else
{
System.out.println("searchRequest failure: " + searchResponse.getLog());
}
}
while (objectsCount >= limit);
for(int i=0; i<uidList.size(); i++)
{
String uid;
try {
uid = uidList.get(i);
// delete user record
GSRequest deleteAccountRequest = new GSRequest(apiKey, secretKey, "accounts.deleteAccount");
//deleteAccountRequest.setAPIDomain("eu1.gigya.com");
deleteAccountRequest.setUseHTTPS(true);
deleteAccountRequest.setParam("UID", uid);
GSResponse deleteAccountResponse = deleteAccountRequest.send();
if(deleteAccountResponse.getErrorCode()==0)
{
}
else
{
System.out.println("deleteAccountResponse failure: " + deleteAccountResponse.getLog());
}
} catch (Exception e) {
}
}

Generate a lot of data in a list and generate the file

I have a table in the database that has about 2.3 million records.
I need to export this data to a csv file through a java / web application.
I'm using JPA / Hibernate. But I'm having trouble.
HibernateEntityManager hem = this.getEntityManager().unwrap(HibernateEntityManager.class);
Session session = hem.getSession();
org.hibernate.Query qu =
session.createSQLQuery("select li.* from ligacoes li").
setFetchSize(Integer.MIN_VALUE).setReadOnly(true);
ScrollableResults r = qu.scroll(ScrollMode.FORWARD_ONLY);
int count = 0;
while (r.next()) {
But when the program reads about 200,000 records it throws an exception:
Exception in thread "ContainerBackgroundProcessor[StandardEngine[Catalina]]"
java.lang.OutOfMemoryError: Java heap space
I've tried other means, but I'm still having difficulties. I can't export the data directly from the database. The data must be exported through this application.
Can anyone help?
I solved the question.
I split the query. Instead of bringing a very large list, I bring a minor list several times. Pagination.
HibernateEntityManager hem = this.getEntityManager().unwrap(HibernateEntityManager.class);
Session session = hem.getSession();
int pageIn = 1;
int pageFim = 20000;
boolean fim = false;
int count = 0;
while (!fim) {
++count;
org.hibernate.Query qu = session.createSQLQuery("select li.* from ligacoes li where li.operadora='81' "
+ "and length(li.numero_destino) < 8 and li.valor_contrato <> '0'");
qu.setFirstResult(pageIn - 1);
qu.setMaxResults(pageFim);
List<Ligacoes> chamadasVivo = new ArrayList<>(objectToLigacoes(qu.list()));
count += pageFim;
if (chamadasVivo.size() <= 0) {
break;
}
for (Ligacoes li : chamadasVivo) {
//append the file...
}
if (count % 100000 == 0) {
session.flush();
session.clear();
}
pageIn += pageFim;
}

Can't Retrieve Value from zk listbox

Let's say i have a listbox that contain ten items, and then i set five items for every page, so now the listbox have two pages
and the problem is everytime i want to get the value in listbox it only get five items instead ten items.
im using ListItemRenderer on My Listbox
below is my code :
AnnotationConfiguration config = new AnnotationConfiguration();
SessionFactory sessionFactory = config.configure().buildSessionFactory();
Session session = sessionFactory.openSession();
String str = "from Users";
Query q = session.createQuery(str);
List<Users> user = q.list();
session.close();
sessionFactory.close();
list.setModel(new ListModelList<Users>(user));
list.setItemRenderer(new ListitemRenderer() {
#Override
public void render(Listitem item, Object data, int index)
throws Exception {
Users user = (Users) data;
item.setValue(user);
new Listcell(user.getUsername()).setParent(item);
new Listcell(user.getUserrole()).setParent(item);
}
});
}
below my code to get the value :
String name ="";
String role ="";
Users user = new Users();
Listbox box = (Listbox) list.getFellow("win").getFellow("list");
List<Listitem> lists = box.getItems();
//membaca setiap row yang ada pada list
for(Listitem currentList : lists){
List<Component> com = currentList.getChildren();
//membaca setiap column pada row
for (Component currentComp : com){
Listcell lc = (Listcell) currentComp;
if(lc.getColumnIndex() == 0){
name = lc.getLabel();
System.out.println("name = " + name);
}
if(lc.getColumnIndex()==1){
role = lc.getLabel();
System.out.println("role = " + role);
}
}
}
This is the correct behavior. The List is the View and the View
never has more then 5 Items as you discribed.
You want to get the Model so get the Model.
ListModelList lists = (ListModelList)box.getModel();

Categories