First of all, apologize for my grammatical errors. My English level is not good.
I'm trying to read multiple fields that will be columns in a table. But I don't know how do it. Because, I've tried using a loop from getResultList() from query.
I'm using spring boot (jpa + hibernate) with postgsql.
The idea is instead of next code:
public List<Object> readTable(String nameTable) {
String SQL_COLUMN_TABLE_ID = "SELECT table_id FROM " + nameTable + " ORDER BY table_id asc;";
String SQL_COLUMN_GEOM = "SELECT GeometryType(geom) FROM " + nameTable + " ORDER BY table_id asc;";
String SQL_COLUMN_PROPERTIES = "SELECT CAST(properties AS text) FROM " + nameTable + " ORDER BY table_id asc;";
List<String> table_id = executeSQLReadTable(SQL_COLUMN_TABLE_ID);
List<String> geom_type = executeSQLReadTable(SQL_COLUMN_GEOM);
List<String> properties = executeSQLReadTable(SQL_COLUMN_PROPERTIES);
List<Object> results = new ArrayList<>();
for (int i=0; i<table_id.size(); i++) {
List<Object> item = new ArrayList<>();
item.add(table_id.get(i));
item.add(geom_type.get(i));
item.add(properties.get(i));
results.add(item);
}
return results;
}
To use this:
public List<String> readPerfectTable(String nameTable) {
String SQL = "SELECT table_id, CAST(properties AS text), GeometryType(geom) FROM " + nameTable + " ORDER BY table_id asc;";
return executeSQLReadTable(SQL);
}
In this part, I do not know how to use the results of multiple fields from select:
private List<String> executeSQLReadTable(String SQL) {
List<String> results = new ArrayList<>();
try {
Query query = em.createNativeQuery(SQL);
List<?> list = query.getResultList();
for (Object item : list) {
// Here WTF!
results.add(item.toString());
}
} catch(Throwable e) {
throw e;
} finally {
em.close();
}
return results;
}
I solved :D
Thanks a lot :D
private List<Object> executeSQLReadTable(String SQL) {
List<Object> results = new ArrayList<>();
try {
Query query = em.createNativeQuery(SQL);
List<?> result = query.getResultList();
Iterator<?> itr = result.iterator();
while(itr.hasNext()){
Object[] obj = (Object[]) itr.next();
List<Object> row = new ArrayList<>();
row.add(Long.parseLong(String.valueOf(obj[0])));
row.add(String.valueOf(obj[1]));
row.add(String.valueOf(obj[2]));
results.add(row);
}
} catch(Throwable e) {
throw e;
} finally {
em.close();
}
return results;
}
Related
In the below code I am fetching the objects from the hive and passing the tbl_guid to fetch the matches in Mysql and Map will be returned as contains Map<tbl_guid ,uniqueseq>, then the on the based of tbl_guid as key already present the map dRListMap value List<DeletedRecord> DeletedRecord object property tbl_guid will be updated with fetched the uniqueseq fetched from the mysql.
Why am I replacing the tbl_guid with uniqueSeq fetching from the mysql because the on the based with small no corresponding to every tbl_guid which will stored in the HBase later of this, that part of code is not required herein discussion so I haven't posted? I would like to know where is enhancement is required current code.
1st Method
String sql = String.format("select * from %s .HiveTable limit 12", dbName);
Map<String, List<DeletedRecord>> dRListMap = new HashMap<>();
try (Statement stmt = hiveConnection.createStatement(); ResultSet rs = stmt.executeQuery(sql)) {
int i=0;
while ((rs.next())) {
DeletedRecord delRecord = new DeletedRecord(rs.getString(1), rs.getString(2), rs.getString(3),
rs.getString(4), rs.getDate(5));
String key = rs.getString(2);
List<DeletedRecord> recordList = dRListMap.get(key) == null ? new ArrayList<>() : dRListMap.get(key);
recordList.add(delRecord);
dRListMap.put(key, recordList);
i++;
if (i == 10) {
CommonService.fetchUniquForTblGuid(dRListMap);
i=0;
}
}if(i>0) {
CommonService.fetchUniquForTblGuid(dRListMap);
}
} catch (Exception ee) {
LOGGER.error("Exception occurred while fetching the records from table_name", ee);
}
2nd Method
public static void fetchUniquForTblGuid(Map<String, List<DeletedRecord>> dRListMap) {
List<List<DeletedRecord>> valueList = Collections.list(Collections.enumeration(dRListMap.values()));
List<String> values = valueList.stream().flatMap(Collection::stream).map(DeletedRecord::getTblGuid)
.collect(Collectors.toCollection(ArrayList::new));
Map<String, String> tblSeqMap = getTheUniqueNoForGuids(values);
System.out.println(dRListMap);
for (Map.Entry<String, String> map : tblSeqMap.entrySet()) {
if (dRListMap.containsKey(map.getKey())) {
dRListMap.get(map.getKey()).forEach((DeletedRecord del)->del.setTblGuid(map.getValue()));
}
}
System.out.println(dRListMap);
dRListMap.clear();
}
3rd Method
public static Map<String, String> getTheUniqueNoForGuids(List<String> tableGuids) {
Map<String, String> guidVsUnique = new HashMap<>();
String tableGuidStr = listToCommaDelimitedString(tableGuids);
String fetchthequniforguid = "select distinct tbl_guid,unique_sequ from " + sqlProp.getProperty("database")
+ ".mysql table where tbl_guid in (" + tableGuidStr + ")";
try (PreparedStatement prep = mysqlConnection.prepareStatement(fetchthequniforguid);
ResultSet res = prep.executeQuery()) {
LOGGER.info(String.format("Mysql query %s ", fetchthequniforguid));
while (res.next()) {
guidVsUnique.put(res.getString(1), res.getString(2));
}
} catch (SQLException e) {
LOGGER.info(String.format("Error while executing %s in mysql and occurred %s ", fetchthequniforguid, e));
}
return guidVsUnique;
}
4th Method
public static String listToCommaDelimitedString(List<String> requestIds) {
StringBuffer buffer = new StringBuffer();
if (requestIds.size() == 1)
buffer.append("'" + requestIds.get(0) + "'");
else if (requestIds.size() > 1) {
buffer.append("'");
for (int i = 0; i < requestIds.size(); i++) {
if (i == requestIds.size() - 1)
buffer.append(requestIds.get(i) + "'");
else
buffer.append(requestIds.get(i) + "', '");
}
}
return buffer.toString();
}
I have found below code buggy as it degrades the performance of extjs3 grid, i am looking for possibilities of optimization at query or code level, as per my analysis, if we extract out the query there are two nested inner queries which are responding slow, in addition, the code inside while loop trying to find the unique id, can't we have distinct in query, or joins rather than inner queries.
Please suggest me the best practice to follow in order to achieve optimization.
public boolean isSCACreditOverviewGridVisible(String sessionId) {
Connection conn = null;
ResultSet rs = null;
PreparedStatement ps = null;
boolean result = false;
try {
CommonUtility commUtil = new CommonUtility();
List<String> hmIds = new ArrayList<String>();
Map<String, String> tmStockMap = new TreeMap<String, String>();
Set<String> setRecentCertificate = new HashSet<String>();
String managerAccountId = sessionInfo.getMembershipAccount();
String stockQuery = " select memberId , RootCertficateId from stockposition sp where sp.stocktype = 'TR' and sp.memberId "
+ " IN ( select hm2.accountId from "
DATALINK
+ ".holdingmembers hm2 "
+ " where hm2.holdingId = ( select holdingId from "
DATALINK
+ ".holdingmembers hm1 where hm1.accountId = ? )) "
+ " order by sp.createdDate desc ";
conn = getChildDBConnection();
if (null != conn) {
ps = conn.prepareStatement(stockQuery);
ps.setString(1, managerAccountId);
rs = ps.executeQuery();
if (null != rs) {
while (rs.next()) {
String memberId = rs.getString("memberId");
String rootCertficateId = rs
.getString("RootCertficateId");
if (tmStockMap.containsKey(rootCertficateId)) {
continue;
}
hmIds.add(memberId);
tmStockMap.put(rootCertficateId, memberId);
}
}
rs.close();
ps.close();
if (null != hmIds && !hmIds.isEmpty()) {
String inIds = commUtil.getInStateParam(hmIds);
String mostRecentLicense = "Select RootCertificateId , memberaccountid from "
+ OctopusSchema.octopusSchema
+ ".certificate c where c.memberaccountid IN ("
+ inIds
+ ") and c.isrootcertificate=0 and c.certificationstatusid > 1 order by c.modifieddate desc";
ps = conn.prepareStatement(mostRecentLicense);
rs = ps.executeQuery();
if (null != rs) {
while (rs.next()) {
String rootCertficateId = rs
.getString("RootCertificateId");
String memberaccountid = rs
.getString("memberaccountid");
if (setRecentCertificate.contains(memberaccountid)) {
continue;
}
setRecentCertificate.add(memberaccountid);
if (tmStockMap.containsKey(rootCertficateId)) {
result = true;
break;
}
}
}
rs.close();
ps.close();
} else {
result = false;
}
}
} catch (Exception e) {
LOGGER.error(e);
} finally {
closeDBReferences(conn, ps, null, rs);
}
return result;
}
QUERY:
select RootCertficateId,memberId from stockposition sp where sp.stocktype = 'TR' and sp.memberId
IN ( select hm2.accountId from
DATALINK.holdingmembers hm2
where hm2.holdingId = ( select holdingId from
DATALINK.holdingmembers hm1 where hm1.accountId = '4937' ))
order by sp.createdDate DESC;
One quick approach would be a substition of your IN by EXISTS. If your inner queryes return a lot of rows, it would be a lot more efficient. It depends if your subquery returns a lot of results.
SQL Server IN vs. EXISTS Performance
In my code i have used List < Tuple > to capture the query results by joining various
tables and mapping to DTO object. This code works fine in the main. But
when i try to create a test case, i'm unable to cover the List < Tuple > code.
Please provide your inputs.
For Ex :
#SuppressWarnings("unchecked")
private List<FeedbackDTO> getList(String sortingProperty, String direction, UUID workflowId, UUID categoryId,
String type) {
StringBuilder query = new StringBuilder(
"select feedback.id, feedback.workflowId, user.userName, user.firstName, "
+ "user.lastName, feedback.submittedDate, country.countryName, "
+ "region.regionName, feedback.comments, feedback.ratings, feedback.acknowledged "
+ "from Feedback feedback, User user, Country country, Region region "
+ "where feedback.userId = user.id and user.countryId = country.id and user.regionId = region.id "
+ "and feedback.workflowId = " + "'" + workflowId + "'" + " and feedback.categoryId = " + "'"
+ categoryId + "'" + " and feedback.type = " + "'" + type + "'" + " order by ");
if (sortingProperty.equalsIgnoreCase("firstName")) {
query.append("user.firstName ");
}
query.append(direction);
Query queryList = entityManager.createNativeQuery(query.toString(), Tuple.class);
List<Tuple> tupleList = queryList.getResultList();
List<FeedbackDTO> feedbackList = new ArrayList<FeedbackDTO>();
for (Tuple tuple : tupleList) {
FeedbackDTO feedbackDTO = new FeedbackDTO();
feedbackDTO.setId(UUID.fromString((String) tuple.get("id")));
feedbackDTO.setUserName((String) tuple.get("userName"));
feedbackDTO.setFirstName((String) tuple.get("firstName"));
feedbackDTO.setLastName((String) tuple.get("lastName"));
feedbackDTO.setCountryName((String) tuple.get("countryName"));
feedbackDTO.setAcknowledged((Boolean) tuple.get("acknowledged"));
feedbackDTO.setRegionName((String) tuple.get("regionName"));
feedbackDTO.setComments((String) tuple.get("comments"));
feedbackDTO.setSubmittedDate((Date) tuple.get("submittedDate"));
feedbackDTO.setRatings((Double) tuple.get("ratings"));
feedbackList.add(feedbackDTO);
}
return feedbackList;
}
In My Test Case:
#Test
public void testGetFeedbackListNoFeedback() {
try {
Query queryList = mock(Query.class);
FeedbackTestDTO feedback = new FeedbackTestDTO();
feedback.setId(id);
feedback.setSolutionId(solutionId);
feedback.setComments("Please swich-on the power");
feedback.setType("Alternate Solution");
List<Object> tupleList = new ArrayList<>();
tupleList.add(feedback);
StringBuilder query = new StringBuilder(
"select * from feedback order by user.firstName ASC");
Sort sort = new Sort("firstName:ASC");
Pageable pageable = PageRequest.of(0, 20, sort);
when(entityManager.createNativeQuery(query.toString(), javax.persistence.Tuple.class)).thenReturn(queryList);
when(queryList.getResultList()).thenReturn(tupleList);
this.mockFeedbackListDTO = feedbackServiceImpl.getFeedbackList(workflowId, categoryId, "", "",
"2019-08-29T01:00:00Z", "2019-08-29T13:00:00Z", "5", pageable, true);
assertEquals(201, this.mockFeedbackListDTO.getCode());
} catch (BusinessException | ParseException be) {
assertEquals("No feedback from users", accessor.getMessage(be.getLocalizedMessage()));
}
}
List<Tuple> tupleList = new ArrayList<>();
NativeQueryTupleTransformer nativeQueryTupleTransformer = new NativeQueryTupleTransformer();
tupleList.add((Tuple)nativeQueryTupleTransformer.transformTuple(new BigDecimal[]{new BigDecimal(123),new BigDecimal(123),new BigDecimal(123)},new String[]{"0","1","2"} ));
tupleList.add((Tuple)nativeQueryTupleTransformer.transformTuple(new BigDecimal[]{new BigDecimal(123),new BigDecimal(123),new BigDecimal(123)},new String[]{"0","1","2"} ));
tupleList.add((Tuple)nativeQueryTupleTransformer.transformTuple(new BigDecimal[]{new BigDecimal(123),new BigDecimal(123),new BigDecimal(123)},new String[]{"0","1","2"} ));
Mockito.when(service.getRecordRangeForPagination(Mockito.anyString(),Mockit.anyLong(),Mockito.anyString())).thenReturn(tupleList);
It looks like your list is empty, therefore your for-loop is never examined.
Add an assertion that the expected size of the list should be of size 3:
List<Tuple> tupleResults = queryResults.getResultList();
// Check that the list is of size 3
Assert.assertTrue(tupleResults.size() == 3);
for(Tuple t : tupleResults) {
myDtoObject.setName(t.get("name")); //0
myDtoObject.setAge(t.get("age")); //1
myDtoObject.setSalary(t.get("salary"); //2
}
#Test
public void test() {
Query query = mock(Query.class);
List<Tuple> tupleList = new ArrayList<>();
when(query.getResultList().size() > 0).thenReturn(tupleList );
}
i have a query which will return single record with 2 columns from Table
i want to get the result to a List each element hold a column value , but i keep getting ClassCastExceptoion
this is the code :
public List<String> getStatus(Long requestId) {
List result = new ArrayList();
if (requestId != null)
{
StringBuilder querySBuilder = new StringBuilder();
querySBuilder.append(" select R.request_status_id , L.request_status_desc ");
querySBuilder.append(" from Table1 R join Table2 L ");
querySBuilder.append(" on R.request_status_id = L.REQUEST_STATUS_Id ");
querySBuilder.append(" where R.REQUEST_ID = " + requestId);
System.out.print(querySBuilder.toString());
List resultList =
em.createNativeQuery(querySBuilder.toString()).getResultList();
Vector resultVec = (Vector)resultList.get(0);
int id = ((BigDecimal)resultVec.elementAt(0)).intValue();
String statusName = ((String)resultVec.elementAt(0));
System.out.println("id" + id);
System.out.println("name " + statusName);
result.add(id);
result.add(statusName);
if (resultVec == null || resultVec.isEmpty()) {
return new ArrayList<String>();
}
return result;
}
return null;
}
The pattern I would use would be to phrase the incoming native result set as a List<Object[]>, where each object array represents a single record:
Query q = em.createNativeQuery(querySBuilder.toString());
List<Object[]> result = q.getResultList();
for (Object[] row : result) {
int id = (Integer)row[0];
String statusName = (String)row[1];
// do something with the id and statusName from above
}
I think it is a typo.
String statusName = ((String)resultVec.elementAt(0));
The elementAt(1) should be used instead of elementAt(0).
I am fetching data from database in method BillnAmountFetch and getting value in main method I want to assign fetched velue to arrayList ar.
My code to fetch data from database
public List<Object[]> BillnAmountFetch(long cid) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
List<Object[]> obj = null;
try {
String hql = "select count(billNo), sum(total), invoiceDate from BillDetails "
+ "where client.id=:cid "
+ "group by invoiceDate "
+ "order by invoiceDate DESC";
Query query = session.createQuery(hql);
query.setParameter("cid", cid);
obj = query.list();
tx.commit();
} catch (HibernateException e) {
if (tx != null) {
e.printStackTrace();
tx.rollback();
}
} finally {
session.close();
}
return obj;
}
Following is my code to print data received from above method
public static void main(String[] args) {
BillDAO bdo = new BillDAO();
List<Object[]> lst = bdo.BillnAmountFetch(1);
BillDetails bd = new BillDetails();
ArrayList<BillDetails> ar = new ArrayList<BillDetails>();
Object[] count = lst.get(0);
Object[] amount = lst.get(1);
Object[] invoice_dts = lst.get(2);
System.out.println("-----------Total Bills---------- ");
for (int x = 0; x < count.length; x++) {
System.out.println("Total bills " + count[x]);
}
System.out.println("-------Total Amount--------- ");
for (int x = 0; x < amount.length; x++) {
System.out.println("Amount " + amount[x]);
}
System.out.println("----------Total Invoice date---------- ");
for (int x = 0; x < invoice_dts.length; x++) {
System.out.println("dates " + invoice_dts[x]);
}
}
Output of the above program is
-----------Total Bills----------
Total bills 3
Total bills 7281.00
Total bills 2014-07-15
-------Total Amount---------
Amount 7
Amount 14841.00
Amount 2014-07-12
----------Total Invoice date----------
dates 3
dates 1294.00
dates 2014-07-11
BillDetails.java
public class BillDetails implements java.io.Serializable {
private Date invoiceDate;
private long totalBills;
private BigDecimal totalAmount;
//getter and setter
}
How to properly assing values to ArrayList object ar
EDIT: If not able to assign in ar then can we assign all count to one array or list similar for others.
I have to display values in jsp page.
I am fetching data from database in method BillnAmountFetch and getting value in main method I want to assign fetched velue to arrayList ar.
You can't, you'll have to do the copy yourself and cast/convert the elements appropriately.
Note that BillnAmountFetch returns List<Object[]> (a list of object arrays), and you're saying you want to assign it to ArrayList<BillDetails>.
So there are three major issues there:
A List<Object[]> is allowed to contain Object[] instances, but an ArrayList<BillDetails> is not allowed to contain Object[] instances; the items in the list are required to be BillDetails instances.
List<Object[]> could be any kind of list (LinkedList, Stack), it doesn't have to be an ArrayList, but ar is declared as an ArrayList (specifically).
It seems unlikely that BillDetails is assignment-compatible with Object[] (an array of objects).
Apart from T. J. Crowders suggestion you can map your model entity as Hibernate entity like below:
#Entity
public class BillDetails implements java.io.Serializable {
// some other related annotations
private Date invoiceDate;
private long totalBills;
private BigDecimal totalAmount;
//getter and setter
}
then you can get that automatic binding of ArrayList< BillDetails > by Hibernate, when you do this :
Query query = session.createQuery(hql , BillDetails.Class);
you need to search furthermore about it though:
I got the solution. I may not be able to express my question properly.
I want Scalar results.
What I want is below
public List<BillDetails> BillnAmountFetch(long cid) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
ArrayList<BillDetails> ar = new ArrayList<BillDetails>();
BillDetails bd = null;
try {
String hql = "select count(billNo), sum(total), invoiceDate from BillDetails "
+ "where client.id=:cid "
+ "group by invoiceDate "
+ "order by invoiceDate DESC";
Query query;
query = session.createQuery(hql);
query.setParameter("cid", cid);
Iterator results = query.list().iterator();
while (results.hasNext()) {
Object[] row = (Object[]) results.next();
Long count = (Long) row[0];
BigDecimal amount = (BigDecimal) row[1];
Date dt = (Date) row[2];
System.out.println(count + " " + amount + " " + dt);
bd = new BillDetails();
bd.setTotalBills(count);
bd.setTotalAmount(amount);
bd.setInvoiceDate(dt);
ar.add(bd);
}
System.out.println("--------------------------");
tx.commit();
} catch (HibernateException e) {
if (tx != null) {
e.printStackTrace();
tx.rollback();
}
} finally {
session.close();
}
return ar;
}
public static void main(String[] args) {
BillDAO bdo = new BillDAO();
ArrayList<BillDetails> ar = (ArrayList<BillDetails>) bdo.BillnAmountFetch(1);
System.out.println("In main method");
for(BillDetails b:ar){
System.out.println(b.getTotalBills() + " " + b.getTotalAmount() + " " + b.getInvoiceDate());
}
}