Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 363 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Best practice to select data using Spring JdbcTemplate

#1
I want to know what is the best practice to select records from a table. I mentioned two methods below from that I want to know which one is best practice to select the data from a table using Spring [JdbcTemplate](

[To see links please register here]

).

## First example

try {
String sql = "SELECT id FROM tableName WHERE column_name = '" + coulmn value + "'";

long id = jdbcTemplate.queryForObject(sql, Long.class);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(e);
}
}

This throws the following exception:

> Expected 1 actual 0 like

when table doesn't contain any data. My friend told this is not the best practice to select the data. He suggested that the below mentioned code is the only best practice to select data.

## Second example

try {
String countQuery = "SELECT COUNT(id) FROM tableName";

int count = jdbcTemplate.queryForInt(countQuery);
if (count > 0) {
String sql = "SELECT id FROM tableName WHERE column_name = '" + coulmn value + "'";

long id = jdbcTemplate.queryForObject(sql, Long.class);
}
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(e);
}
}

<br>
I'm eager to know the right one or any other best practice.
Reply

#2
Definitely the first way is the best practice, because in the second way you are hitting the database twice where you should actually hit it only once. This can cause performance issues.

What you need to do is catch the exception `EmptyResultDataAccessException` and then return null back. Spring JDBC templates throws back an [EmptyResultDataAccessException][1] exception if it doesn't find the data in the database.

Your code should look like this.

try {
sql = "SELECT id FROM tableNmae WHERE column_name ='"+ coulmn value+ "'";
id= jdbcTemplate.queryForObject(sql, Long.class);
}
catch (EmptyResultDataAccessException e) {
if(log.isDebugEnabled()){
log.debug(e);
}
return null
}


[1]:

[To see links please register here]

Reply

#3
**Better way to Use ifNull in query** so if there is null then you get 0
Eg.-

sql = "SELECT ifNull(id,0) FROM tableName WHERE column_name ='"+ coulmn value+ "'";


Using this way you can get as default 0 otherwise your Id
Reply

#4
I am facing similar scenario and found a cleaner solution when using ResultSetExtractor instead of RowMapper

jdbcTemplate.query(DBConstants.GET_VENDOR_DOCUMENT, new Object[]{vendorid}, rs -> {

if(rs.next()){
DocumentPojo vendorDoc = new DocumentPojo();
vendorDoc.setRegDocument(rs.getString("registrationdoc"));
vendorDoc.setMsmeLetter(rs.getString("msmeletter"));
vendorDoc.setProprietorshipDocument(rs.getString("propertiershipformat"));
vendorDoc.setNeftDocument(rs.getString("neftdoc"));
vendorDoc.setPanCardDocument(rs.getString("pancard"));
vendorDoc.setCancelledChequeDoc(rs.getString("cheque"));
return vendorDoc;
}
else {
return null;
}

});

If no result is found from database, I had put a if condition for resultset and return null reference. So, I didn't need to try catch the code and pass two queries to database.

Main advantage of ResultSetExtractor (in this scenario) is **with ResultsetExtractor you will need to iterate through the result set yourself, say in while loop.**

More Points can be found here [here][1]


[1]:

[To see links please register here]


Reply

#5
This is queryForObject method source code

@Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws
DataAccessException {
List<T> results = this.query(sql, rowMapper);
return DataAccessUtils.nullableSingleResult(results);
}

DataAccessUtils.nullableSingleResult

@Nullable
public static <T> T nullableSingleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
if (CollectionUtils.isEmpty(results)) {
throw new EmptyResultDataAccessException(1);
} else if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, results.size());
} else {
return results.iterator().next();
}
}

dunno why they throw exception on empty collection, probably this is just a copy-paste from method above

public static <T> T requiredSingleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
if (CollectionUtils.isEmpty(results)) {
throw new EmptyResultDataAccessException(1);
} else if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, results.size());
} else {
return results.iterator().next();
}
}

One more step above the method they shoult have used

@Nullable
public static <T> T singleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
if (CollectionUtils.isEmpty(results)) {
return null;
} else if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, results.size());
} else {
return results.iterator().next();
}
}

NOW SOLUTION helped me:
Extend JdbcTemlate class (you can construct it with DataSource injected)
and overrride the queryForObject method:

@Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
List<T> results = this.query(sql, rowMapper);
return DataAccessUtils.singleResult(results);
}

now work with your implementation
Don't forget to check if it works on spring version update (very unlikely IMHO)
Reply

#6
The best way to get row from a table by condition in case there might be no data in this table - use ```query``` with ```ResultSetExtractor```

```kotlin
fun findDailyReport(date: LocalDate): String? {
val sql = """select * from reports_table where report_date = :date"""
val map = MapSqlParameterSource("date", date)
return jdbcTemplate.query(sql, map, ResultSetExtractor { rs ->
if (rs.next()) {
rs.getString("report")
} else {
log.warn("There is no daily report for the date: $date")
null
}
})
}
```

If you need to check if a row exists in a table, here is a good solution.
In this case, all records in the table are unique:
```kotlin
fun checkReportExists(date: LocalDate): Boolean {
val sql = """select 1 from reports_table where report_date = :date"""
val map = MapSqlParameterSource("date", date)
return jdbcTemplate.query(sql, map, ResultSetExtractor { rs -> rs.next() })!!
}
```
Second solution:
```kotlin
fun checkReportExists(date: LocalDate): Boolean {
val sql = """select count(1) from reports_table where report_date = :date"""
val map = MapSqlParameterSource("date", date)
return jdbcTemplate.queryForObject(sql, map, Int::class.java)!! > 0
```
Last one solution:
```kotlin
fun checkReportExists(date: LocalDate): Boolean {
val sql = """select exists(select 1 from reports_table where report_date = :date)"""
val map = MapSqlParameterSource("date", date)
return jdbcTemplate.queryForObject(sql, map, Boolean::class.java)!!
```
P.S. Last solution is the [fastest](

[To see links please register here]

) for checking if row exists.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through