Use ResultSet object in JSP without JSTL - model-view-controller

I want to pass my query's result i.e ResultSet to JSP just for the display as i am using MVC framework.
My Servlet Code:
Connection c=Connectivity.dbConnect();
PreparedStatement ps=c.prepareStatement("select role from login where userid=? and password=?");
ps.setString(1,userid);
ps.setString(2,pass);
ResultSet rs=ps.executeQuery();
if(rs.next())
{
if(rs.getString(1).equals("admin"))
{
ps=c.prepareStatement("select * from user where userid=?");
ps.setString(1,userid);
rs=ps.executeQuery();
Result r=ResultSupport.toResult(rs);
request.setAttribute("res",r);
rs.close();
c.close();
return mapping.findForward("us");//to User.jsp
}
}
I've used ResultSupport.toResult() to forward it to JSP (forwarded by 'us' mapping) but that requires JSTL code in JSP :
User.jsp -
<c:forEach var="data" items="${requestScope.res.rows}">
<h1>${data.userid}</h1>
<h2>${data.name}</h2>
<h2>${data.password}</h2>
<h2>${data.emailid}</h2>
</c:forEach>
Moreover if i directly pass ResultSet like request.setAttribute("ResultSet",rs); i wouldn't be able to close the connection in JSP.
This Code works fine but i do NOT want to use JSTL/EL or Lists , i want to use scriplets in JSP that can handle Result or ResultSet attribute from Servlet.

You can overcome your issue like this:
1) In your database manipulation class use a POJO to add in results from ResultSet.
Contacts myContact = new Contacts();
myContact.setOffice(rs.getString("office1"));
myContact.setMail(rs.getString("xx#xx.com"));
2) Then use a List to store your results
List<Contacts> myList = new ArrayList<Contacts>();
myList.add(myContact);
3) Pass the list to your request/session Object and close ResultSet/Connection there
request.setAttribute("LIST",myList);
rs.close();
conn.close()
4) In JSP get the List and iterate over it anyway you want
ArrayList<Contacts> myList = (ArrayList<Contacts>) request.getAttribute("LIST");
for(Contacts obj: myList){
out.print(obj.getMail());
....
....
}

Related

In Spring Boot, how to I get the column names from a StoredProcedureQuery result?

I am working on creating a simple utility that allows our users to execute a pre-selected list of stored procedures that return a simple list result set as a JSON string. The result set varies based on the selected procedure. I am able to get the results easily enough (and pass back as JSON as required), but the results don't include the column names.
The most common answer I found online is to use ResultSetMetaData or NativeQuery, but I couldn't figure out how to extract the metadata or transform the query properly using a StoredProcedureQuery object. How do I get the column names from a StoredProcedureQuery result?
Here is my code:
#SuppressWarnings("unchecked")
public String executeProcedure(String procedure, String jsonData) {
//Set up a call to the stored procedure
StoredProcedureQuery query = entityManager.createStoredProcedureQuery(procedure);
//Register and set the parameters
query.registerStoredProcedureParameter(0, String.class, ParameterMode.IN);
query.setParameter(0, jsonData);
String jsonResults = "[{}]";
try {
//Execute the query and store the results
query.execute();
List list = query.getResultList();
jsonResults = new Gson().toJson(list);
} finally {
try {
//Cleanup
query.unwrap(ProcedureOutputs.class).release();
} catch(Exception e) {
e.printStackTrace();
}
}
return jsonResults;
}
The challenge is to get a ResultSet. In order to list the column names you need a ResultSet to do the following to access metadata. (Column names are metadata)
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
System.out.println("Column name: "+resultSetMetaData.getColumnName(1));
System.out.println("Column type: "+resultSetMetaData.getColumnTypeName(1));
You can't get ResultSet (or metadata) from javax.persistence.StoredProcedureQuery or from spring-jpa Support JPA 2.1 stored procedures returning result sets
You can with low-level JDBC as follows:
CallableStatement stmnt = conn.prepareCall("{call demoSp(?, ?)}");
stmnt.setString(1, "abcdefg");
ResultSet resultSet1 = stmnt.executeQuery();
resultSet1.getMetaData(); // etc

How to add ajax to dynamically created primefaces input fields

I want to create a page to allow users to update a mysql table. This table can be changed by client admins so I have to read the table schema and create fields on the fly. I got the basic code for doing that from How to create dynamic JSF form fields and the ajax code from How to add ajax validation to programmatically generated primefaces component.
To create a proof of concept page I use the following code (note, I'm using primefaces):
for (int idx = 1; idx < 3; idx++) {
UIInput input = new InputText();
input.setId("text" + idx);
ValueExpression targetExpression = facesContext.getApplication().getExpressionFactory().createValueExpression(facesContext.getELContext(), "#{viewMakeFields.value}", String.class);
input.setValueExpression("value", targetExpression);
AjaxBehavior ab = new AjaxBehavior();
ab.setAsync(true);
ab.setProcess("text"+idx);
input.addClientBehavior("blur", ab); // "change" doesn't work either
form.getChildren().add(input);
}
Then, in the getter and setter, I'm getting the component ID to identify which field is changed:
public static String getCallingComponentID() {
UIComponent component = UIComponent.getCurrentComponent(FacesContext.getCurrentInstance());
return component.getId();
}
public String getValue() {
String id = getCallingComponentID();
System.out.println("getValue " + id);
return text1;
}
public void setValue(String text1) {
String id = getCallingComponentID();
System.out.println("setValue " + id);
this.text1 = text1;
}
The ajax isn't firing and when I click the submit button I get (and I know mixing partial and full submits isn't good):
INFO: getValue text1
INFO: getValue text2
INFO: getValue text1
INFO: getValue text2
INFO: setValue j_id1
INFO: setValue j_id1
INFO: getValue text1
INFO: getValue text2
I see two possible solutions: get ajax working so that the component calling the setter has the correct id or get the form submit to identify which child is calling the setter. The former is preferable since I want to disable the save button until something has changed but I'm willing to accept the latter at this point. Any help would be much appreciated.
Turns out this code does work. Somewhere in my meandering the error changed and I didn't understand the significance of that. Replacing head with h:head in the xhtml file that I was adding the fields to makes ajax work.

getHibernateTemplate().find(String query,Object values) equivalent in Hibernate

I am working in Hibernate with Spring and used Spring Hibernate template (getHibernateTemplate().find(String query,Object values)) for replacing positioned parameter with values.
My query is:
from className classObject where classObject.variableOne = ? and classObject.variableTwo = ?
and my parameter is an ArrayList<String> with 2 values.
The getHibernateTemplate().find(String query,Object values) assigned the ArrayList values automatically in the where clause (As you can see, I didn't bind parameters manually) and returned me the result.
Now, I removed spring from my application and using only hibernate. So I would like to know,
Is there any equivalent method available in hibernate (Session or
Query) classes which gives same functionality as above where I will pass HQL and values?
Thanks in Advance.
You have to use something like below
private void setParamValues(final String[] paramValues, SQLQuery query) {
if (paramValues != null && paramValues.length > 0) {
for (int liCnt = 0; liCnt < paramValues.length; liCnt++) {
query.setString(liCnt, paramValues[liCnt]);
}
}
}
SQLQuery will replace the ? with passed parameter's value. Keep in mind sequence in the paramValues array should be the same as wrote in the query.
Above has been worked in my case, am sure this will work in your case as well.
This is not Hibernate method, your have to use this method before calling the database.

How to use two java bean to display data in a jsp

I want to display user's detail in a jsp. user's email, name is in one bean. which i am getting in a PagedListHolder. now i need date too which is in another bean . how can i add this date to PagedListHolder. i am using spring mvc framework
public String listUsers(Map<String, Object> map, #RequestParam(value="p", required=false) Integer p) {
PagedListHolder pagedListHolder = new PagedListHolder(usersService.listUsers());
map.put("date11", userActivity.getLastSeen_time());
int page = p;
pagedListHolder.setPage(page);
int pageSize = 2;
pagedListHolder.setPageSize(pageSize);
map.put("pagedListHolder", pagedListHolder);
System.out.println(":::::::::");
return "userListView";
}
in jsp i am using it as
<c:forEach items="${pagedListHolder.pageList}" var="user">
<tr onmouseover="ChangeColor(this, true);" onmouseout="ChangeColor(this, false);" onclick="DoNav('${pageContext.request.contextPath}/secure/detailUserView');">
<td>${user.name}</td>
<td>${user.email}</td>
<td>`DATE`</td>
</tr>
</c:forEach>
in jsp in place of DATE i need to display date which is in date bean
If the pagedListHolder stored as "pagedListHolder" in the map is available using ${pagedListHolder}, then the date, stored as "date11" in the map, must also be available using ${date11}.
You can format it using <fmt:formatDate value="{date11}"/>.

Resultset Metadata from Spring JDBCTemplate Query methods

Is there any way I can get resultset object from one of jdbctemplate query methods?
I have a code like
List<ResultSet> rsList = template.query(finalQuery, new RowMapper<ResultSet>() {
public ResultSet mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs;
}
}
);
I wanted to execute my sql statement stored in finalQuery String and get the resultset. The query is a complex join on 6 to 7 tables and I am select 4-5 columns from each table and wanted to get the metadata of those columns to transform data types and data to downstream systems.
If it is a simple query and I am fetching form only one table I can use RowMapper#mapRow and inside that maprow method i can call ResultsetExtractor.extractData to get list of results; but in this case I have complex joins in my query and I am trying to get resultset Object and from that resultset metadata...
The above code is not good because for each result it will return same resultset object and I dont want to store them in list ...
Once more thing is if maprow is called for each result from my query will JDBCTemplate close the rs and connection even though my list has reference to RS object?
Is there any simple method like jdbcTemplate.queryForResultSet(sql) ?
Now I have implemented my own ResultSet Extractor to process and insert data into downstream systems
sourceJdbcTemplate.query(finalQuery, new CustomResultSetProcessor(targetTable, targetJdbcTemplate));
This CustomResultSetProcessor implements ResultSetExtractor and in extractData method I am calling 3 different methods 1 is get ColumnTypes form rs.getMetaData() and second is getColumnTypes of target metadata by running
SELECT NAME, COLTYPE, TBNAME FROM SYSIBM.SYSCOLUMNS WHERE TBNAME ='TABLENAME' AND TABCREATOR='TABLE CREATOR'
and in 3rd method I am building the insert statement (prepared) form target columntypes and finally calling that using
new BatchPreparedStatementSetter()
{
#Override
public void setValues(PreparedStatement insertStmt, int i) throws SQLException{} }
Hope this helps to others...
Note that the whole point of Spring JDBC Template is that it automatically closes all resources, including ResultSet, after execution of callback method. Therefore it would be better to extract necessary data inside a callback method and allow Spring to close the ResultSet after it.
If result of data extraction is not a List, you can use ResultSetExtractor instead of RowMapper:
SomeComplexResult r = template.query(finalQuery,
new ResultSetExtractor<SomeComplexResult>() {
public SomeResult extractData(ResultSet) {
// do complex processing of ResultSet and return its result as SomeComplexResult
}
});
Something like this would also work:
Connection con = DataSourceUtils.getConnection(dataSource); // your datasource
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(query); // your query
ResultSetMetaData rsmd = rs.getMetaData();
Although I agree with #axtavt that ResultSetExtractor is preferred in Spring environment, it does force you to execute the query.
The code below does not require you to do so, so that the client code is not required to provide the actual arguments for the query parameters:
public SomeResult getMetadata(String querySql) throws SQLException {
Assert.hasText(querySql);
DataSource ds = jdbcTemplate.getDataSource();
Connection con = null;
PreparedStatement ps = null;
try {
con = DataSourceUtils.getConnection(ds);
ps = con.prepareStatement(querySql);
ResultSetMetaData md = ps.getMetaData(); //<-- the query is compiled, but not executed
return processMetadata(md);
} finally {
JdbcUtils.closeStatement(ps);
DataSourceUtils.releaseConnection(con, ds);
}
}

Resources