Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
private String customer_name;
private String road_number;
private String locomotive_type_code;
private String in_service_date;
private String part_number;
private String emission_tier_type;
private String airbrake_type_code;
private String lms_fleet;
private String aar_road;
private String locomotive_status_code;
// Getters and Setters
Here is my RowMapper implementation
//RowMapper
public class CustomerDataResponseMapper implements RowMapper {
@Override
public Object mapRow(ResultSet rs, int count) throws SQLException {
CustomerData customerData = new CustomerData();
customerData.setLocomotive_id(rs.getString("locomotive_id"));
customerData.setCustomer_name(rs.getString("customer_name"));
customerData.setRoad_number(rs.getString("road_number"));
customerData.setLocomotive_type_code(rs.getString("locomotive_type_code"));
customerData.setIn_service_date(rs.getString("in_service_date"));
customerData.setPart_number(rs.getString("part_number"));
customerData.setEmission_tier_type(rs.getString("emission_tier_type"));
customerData.setAirbrake_type_code(rs.getString("airbrake_type_code"));
customerData.setLms_fleet(rs.getString("lms_fleet"));
customerData.setAar_road(rs.getString("aar_road"));
customerData.setLocomotive_status_code(rs.getString("locomotive_status_code"));
return customerData;
And finally, I got my DaoImpl class here
//DaoImpl
public String getCustomersData(String locoId, String custName, String roadNumber) {
CustomerData resultSet = null;
String str = "";
if (locoId != null && locoId.length() > 0 && !(locoId.equals("0"))) {
str = "select locomotive_id,customer_name,road_number,model_type as locomotive_type_code,to_char(in_service_date,'yyyy-mm-dd') as in_service_date,loco_part_number as part_number, emission_tier_type as emission_tier_type, "
+ "air_brake_type as airbrake_type_code,lms_fleet,aar_road,locomotive_status_code from get_rdf_explorer.get_rdf_locomotive_detail where locomotive_id = ?";
resultSet = (CustomerData) jdbcTemplate.queryForObject(str, new CustomerDataResponseMapper(), locoId);
} else if ((custName != null && custName.length() > 0)
&& (roadNumber != null && roadNumber.length() > 0 && roadNumber != "0")) {
str = "select locomotive_id,customer_name,road_number,model_type as locomotive_type_code,to_char(in_service_date,'yyyy-mm-dd') as in_service_date,loco_part_number as part_number, emission_tier_type as emission_tier_type, "
+ "air_brake_type as airbrake_type_code,lms_fleet,aar_road,locomotive_status_code from get_rdf_explorer.get_rdf_locomotive_detail where customer_name = ? and road_number= ?";
resultSet = (CustomerData) jdbcTemplate.queryForObject(str, new CustomerDataResponseMapper(), custName, roadNumber);
} else {
str = "select distinct customer_name from get_rdf_explorer.get_rdf_locomotive_detail order by customer_name asc";
resultSet = (CustomerData) jdbcTemplate.queryForObject(str, new CustomerDataResponseMapper());
return resultSet.toString();
How can I conditionally get the values from the resultSet based on whether a particular column is present in the resultSet or not. As I am not getting all the columns all the time through my queries.
I am getting SQL bad grammar exception when specific column is not present in resultSet. For example when the third query to get distinct customer names get executed, in the resultSet only customerName would be there, but not the other columns.
It would be really a great help. Thanks a lot in advance.
–
–
–
Since you already have 3 separate queries why not have 3 separate RowMapper
s, one for each query. Your queries "know" what columns they return, so you can easily create those classes for RowMapper
.
If you really want High-Fidelity solution you could create abstract base RowMapper
for common parts and 3 subclasses for parts specifig to the query.
–
–
You can use a generic method which investigates the ResultSet
's columns
@SuppressWarnings("unchecked")
public <T> T getColIfPresent(ResultSet rs, String columnName) throws SQLException {
ResultSetMetaData metaData = rs.getMetaData();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
if (columnName.equals(metaData.getColumnName(i))) {
return (T) rs.getObject(columnName);
return null;// not present
Then, in row mapper.
customerData.setLocomotive_id(getColIfPresent(rs, "locomotive_id"));
This has O(n*m) complexity where n - the number of columns checked, m - the number of columns returned in ResultSet
.
If you choose to ignore the SQLException
, at least log it in DEBUG
or TRACE
level in case a different subtype of SQLException
occurs, so that it's not lost.
–
–
Rather than conditionnaly getting columns, you could modify your SQL to match your mapper, like setting other field to empty string or null
(I don't remmember if getString() crashes on null or something).
For example your third query would look like:
select distinct customer_name, null as "locomotive_id",'' as "road_number", null as model_type, [etc.] from get_rdf_explorer.get_rdf_locomotive_detail order by customer_name asc
So each query would have the same columns and you don't have to adapt. This is the solution if you d'ont really want/can't change the rowMapper (or want to have only one for this object).
But honestly I would go with ikketu's solution. You should make a separate mapper for the thrid query (plus, it wouldn't be complicated). Not goign with an ORM is a choice but you'll have redundancy problem anyway. I would even add that you should separate some of the logic in your code, this methods seems to be doing different thing (business logic depending on input, and database access) it's not very clear (after the third if, create a method like "getdistinctName()" or something).
Santosh, a quick workaround could be passing a flag to your rowmapper while supplying it to jdbcTemplate. I've done so many times to avoid multiple rowmapper.
resultSet = (CustomerData) jdbcTemplate.queryForObject(str, new CustomerDataResponseMapper(1), custName, roadNumber);
For the above changes, you need to overload constructor with the default one. Then you need to use your flag i.e. instance variable in mapRow() method to handle each situation separately.
You can use BeanPropertyRowMapper
which will directly map field names of target class. Here is the javadoc.
The names are matched either directly or by transforming a name separating the parts with underscores to the same name using "camel" case. So, you can use it any other classes whenever you want to map directly to a class. Just have to make sure selected fields are remain in target class. And a default or no-arg constructor.
Following example to get CustomerData
using BeanPropertyRowMapper
RowMapper<CustomerData> mapper = new BeanPropertyRowMapper<>(CustomerData.class);
List<CustomerData> result = jdbc.query("your query string...", mapper, query_args...);
So, then you can return first object or whatsoever.
–
–
My advice is to split your getCustomersData
into three different methods. If you definitely want to ignore this advice, the quick and dirty solution is to protect the rs.getString(...)
calls inside your rowMapper. Something like this:
try {
customerData.setLocomotive_id(rs.getString("locomotive_id"));
} catch (SQLException e) {
// ignore this exception. DO NOT TRY THIS AT HOME!
–
–
–
If numbers of columns are not fix then you should go with ColumnMapRowMapper
based on its implementation even you do not require to create separate concrete class of RowMapper
(i.e. CustomerDataResponseMapper
) you just need to pass instance of ColumnMapRowMapper
in query as given below:
ColumnMapRowMapper rowMapper = new ColumnMapRowMapper();
List<Map<String, Object>> customerDataList = jdbcTemplate.query(sql,rowMapper, args);
Now you should create one method to manipulate this map like
private CustomerData fillCustomerDataFromMap(List<Map<String, Object>> customerDataList){
CustomerData customerData = new CustomerData();
for(Map<String, Object> map: customerDataList ){
customerData.setColumn(map.get("columnName"));
customerData.setColumn(map.get("columnName"));
customerData.setColumn(map.get("columnName"));
customerData.setColumn(map.get("columnName"));
.........
.........
.........
return customerData;
This is more readable and remove the boilerplate codes and not throw any exception if column name is not present in map (it will simply returns null
if column name is not present in map)
Reference of ColumnMapRowMapper
:
https://github.com/spring-projects/spring-framework/blob/master/spring-jdbc/src/main/java/org/springframework/jdbc/core/ColumnMapRowMapper.java
–
Based on the logic of your queries i see that before executing sql query in get_rdf_explorer.get_rdf_locomotive_detail
there are some records and 3 options of getting of necessary (unique) record are possible:
by locomotive_id
by customer_name
and road_number
ANY record (all records must have same customer_name
, else SQL distinct
without any conditions return more than 1 row)
So, in the 3rd option you can get any 1 record with all attributes equal to NULL
and NOT NULL
customer_name
value:
str = "select null as locomotive_id, customer_name, null as road_number,
<other attributes> from get_rdf_explorer.get_rdf_locomotive_detail where
rownum = 1";`
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.