QueryForObject and queryForList returned ing objects in spring MVC jdbcTemplate

Source: Internet
Author: User

QueryForObject and queryForList returned ing objects in spring MVC jdbcTemplate

When using spring MVC to build a project, I plan to directly use spring mvc jdbc. If I introduce MySQL, Hibernate, and other ORM, it is too troublesome, so I will directly use Spring framework. jdbc. SpringMVCJDBC provides two data jdbc operation classes: jdbcTemplate and namedParameterJdbcTemplate. They all provide a lot of methods and I will not write them (see the source code ). Now, the question is, how can I map objects returned from the database?

Now that I have a table named "user", I need to return the UserInfo object and List .

The UserInfo object is as follows:

 

package org.andy.shop.entity;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Date;public class UserInfo {private Integer id;private String uname;private Integer unumber;private Date uRegisterTime;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname == null ? null : uname.trim();}public Integer getUnumber() {return unumber;}public void setUnumber(Integer unumber) {this.unumber = unumber;}public Date getuRegisterTime() {return uRegisterTime;}public void setuRegisterTime(Date uRegisterTime) {this.uRegisterTime = uRegisterTime;}}

Here we can use the following method:

 

1. Add a Map conversion method to UserInfo in UserInfo. java.

In the preceding UserInfo, add the conversion method:

public static UserInfo toObject(Map
 
   map) {UserInfo userInfo = new UserInfo();userInfo.setId((Integer) map.get(id));userInfo.setUname((String) map.get(uname));userInfo.setUnumber((Integer) map.get(unumber));userInfo.setuRegisterTime((Date) map.get(uregister_time));return userInfo;}public static List
  
    toObject(List
   
    > lists){List
    
      userInfos = new ArrayList
     
      ();for (Map
      
        map : lists) {UserInfo userInfo = UserInfo.toObject(map);if (userInfo != null) {userInfos.add(userInfo);}}return userInfos;}
      
     
    
   
  
 

Call JdbcTemplate to return the Map set as follows:

 

Public Map QueryForMap (String SQL, Object... args) throws DataAccessException

Public List > QueryForList (String SQL) throws DataAccessException

Call the preceding conversion.

 

@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate NamedParameterJdbcTemplate namedParameterJdbcTemplate;@Overridepublic UserInfo getById(Integer id) {String sql = SELECT * FROM user_info WHERE id = ?;    Map
 
   map = jdbcTemplate.queryForMap(sql, new Object[]{1});return UserInfo.toObject(map);}@Overridepublic List
  
    findAll() {String sql = SELECT * FROM user_info;List
   
    > lists = jdbcTemplate.queryForList(sql);return UserInfo.toObject(lists);}
   
  
 

Summary: This method can be implemented, but the speed is relatively slow.

 

 

2. Use RowMapper to implement the interface

To view the source code of Spring JDBC, we will release it first and provide the following methods:

Public T queryForObject (String SQL, RowMapper RowMapper, Object... args) throws DataAccessException

Public List Query (String SQL, RowMapper RowMapper) throws DataAccessException

In this example, You need to upload a Mapper class that implements RowMapper to return objects. Okay, let's transform UserInfo to implement the RowMapper interface and implement the mapRow method in the interface.

Modify the UserInfo object as follows:

 

Package org. andy. shop. entity; import java. io. serializable; import java. SQL. resultSet; import java. SQL. SQLException; import java. util. date; import org. springframework. jdbc. core. rowMapper;/*** ing data tables and fields ** @ author andy **/public class UserInfo implements RowMapper
 
  
, Serializable {/*****/private static final long serialVersionUID =-8823504831198719837L; private Integer id; private String uname; private Integer unumber; private Date uRegisterTime; public Integer getId () {return id;} public void setId (Integer id) {this. id = id;} public String getUname () {return uname;} public void setUname (String uname) {this. uname = null? Null: uname. trim ();} public Integer getUnumber () {return unumber;} public void setUnumber (Integer unumber) {this. unumber = unumber;} public Date getuRegisterTime () {return uRegisterTime;} public void setuRegisterTime (Date uRegisterTime) {this. uRegisterTime = uRegisterTime;} @ Overridepublic UserInfo mapRow (ResultSet rs, int rowNum) throws SQLException {UserInfo userInfo = new UserInfo (); userInfo. setId (rs. getInt (id); userInfo. setUname (rs. getString (uname); userInfo. setUnumber (rs. getInt (unumber); userInfo. setuRegisterTime (rs. getDate (uregister_time); return userInfo ;}}
 

We can implement the following in the Dao layer:

 

 

@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate NamedParameterJdbcTemplate namedParameterJdbcTemplate;@Overridepublic UserInfo getById(Integer id) {String sql = SELECT * FROM user_info WHERE id = ?;UserInfo userInfo = jdbcTemplate.queryForObject(sql, new UserInfo(),new Object[] { id });return userInfo;}@Overridepublic List
 
   findAll() {String sql = SELECT * FROM user_info;List
  
    userInfos = jdbcTemplate.query(sql, new UserInfo());return userInfos;}
  
 

This method is faster than the previous method.

 

However, when viewing the JDBC source code, we also see the following method:

Public T queryForObject (String SQL, Class RequiredType, Object... args) throws DataAccessException

Public List QueryForList (String SQL, Class ElementType) throws DataAccessException

Can we separate the following calls?

 

UserInfo userInfo = jdbcTemplate. queryForObject (SQL, UserInfo. class,
New Object [] {id });

List UserInfos = jdbcTemplate. queryForList (SQL, UserInfo. class );

 

Run the JUnit test and the results are as follows:

Org. springframework. jdbc. IncorrectResultSetColumnCountException: Incorrect column count: expected 1, actual 4
At org. springframework. jdbc. core. SingleColumnRowMapper. mapRow (SingleColumnRowMapper. java: 88)
At org. springframework. jdbc. core. RowMapperResultSetExtractor. extractData (RowMapperResultSetExtractor. java: 93)
At org. springframework. jdbc. core. RowMapperResultSetExtractor. extractData (RowMapperResultSetExtractor. java: 60)
At org. springframework. jdbc. core. JdbcTemplate $ 1QueryStatementCallback. doInStatement (JdbcTemplate. java: 460)
At org.springframework.jdbc.core.JdbcTemplate.exe cute (JdbcTemplate. java: 405)
At org. springframework. jdbc. core. JdbcTemplate. query (JdbcTemplate. java: 471)
At org. springframework. jdbc. core. JdbcTemplate. query (JdbcTemplate. java: 481)
At org. springframework. jdbc. core. JdbcTemplate. queryForList (JdbcTemplate. java: 516)
At org. andy. shop. dao. Impl. UserInfoDaoImpl. findAll (UserInfoDaoImpl. java: 43)
At org. andy. shop. service. Impl. UserInfoServiceImpl. findAll (UserInfoServiceImpl. java: 31)
At org. andy. shop. test. service. TestUserInfoService. testFindAll (TestUserInfoService. java: 37)
At sun. reflect. NativeMethodAccessorImpl. invoke0 (Native Method)
At sun. reflect. NativeMethodAccessorImpl. invoke (NativeMethodAccessorImpl. java: 57)
At sun. reflect. DelegatingMethodAccessorImpl. invoke (DelegatingMethodAccessorImpl. java: 43)
At java. lang. reflect. Method. invoke (Method. java: 606)
At org. junit. runners. model. FrameworkMethod $1. runReflectiveCall (FrameworkMethod. java: 50)
At org. junit. internal. runners. model. ReflectiveCallable. run (ReflectiveCallable. java: 12)
At org. junit. runners. model. FrameworkMethod. invokeExplosively (FrameworkMethod. java: 47)
At org. junit. internal. runners. statements. InvokeMethod. evaluate (InvokeMethod. java: 17)
At org. springframework. test. context. junit4.statements. RunBeforeTestMethodCallbacks. evaluate (RunBeforeTestMethodCallbacks. java: 73)
At org. springframework. test. context. junit4.statements. RunAfterTestMethodCallbacks. evaluate (RunAfterTestMethodCallbacks. java: 82)
At org. springframework. test. context. junit4.statements. SpringRepeat. evaluate (SpringRepeat. java: 73)
At org. junit. runners. ParentRunner. runLeaf (ParentRunner. java: 325)
At org. springframework. test. context. junit4.SpringJUnit4ClassRunner. runChild (SpringJUnit4ClassRunner. java: 217)
At org. springframework. test. context. junit4.SpringJUnit4ClassRunner. runChild (SpringJUnit4ClassRunner. java: 83)
At org. junit. runners. ParentRunner $ 3.run( ParentRunner. java: 290)
At org. junit. runners. ParentRunner $1. schedule (ParentRunner. java: 71)
At org. junit. runners. ParentRunner. runChildren (ParentRunner. java: 288)
At org. junit. runners. ParentRunner. access $000 (ParentRunner. java: 58)
At org. junit. runners. ParentRunner $2. evaluate (ParentRunner. java: 268)
At org. springframework. test. context. junit4.statements. RunBeforeTestClassCallbacks. evaluate (RunBeforeTestClassCallbacks. java: 61)
At org. springframework. test. context. junit4.statements. RunAfterTestClassCallbacks. evaluate (RunAfterTestClassCallbacks. java: 68)
At org. junit. runners. ParentRunner. run (ParentRunner. java: 363)
At org. springframework. test. context. junit4.SpringJUnit4ClassRunner. run (SpringJUnit4ClassRunner. java: 163)
At org. eclipse. jdt. internal. junit4.runner. JUnit4TestReference. run (JUnit4TestReference. java: 50)
At org. eclipse. jdt. internal. junit. runner. TestExecution. run (TestExecution. java: 38)
At org. eclipse. jdt. internal. junit. runner. RemoteTestRunner. runTests (RemoteTestRunner. java: 467)
At org. eclipse. jdt. internal. junit. runner. RemoteTestRunner. runTests (RemoteTestRunner. java: 683)
At org. eclipse. jdt. internal. junit. runner. RemoteTestRunner. run (RemoteTestRunner. java: 390)
At org. eclipse. jdt. internal. junit. runner. RemoteTestRunner. main (RemoteTestRunner. java: 197)

This indicates that the expected result is 1 and the result is 4 columns. (The database contains one row of data and four columns)

Why? Let's continue to check the JDBC source code,

Public T queryForObject (String SQL, Class RequiredType, Object... args) throws DataAccessException source code is as follows:

 

        @Overridepublic 
 
   T queryForObject(String sql, Class
  
    requiredType, Object... args) throws DataAccessException {return queryForObject(sql, args, getSingleColumnRowMapper(requiredType));}
  
 

 

GetSingleColumnRowMapper only obtains UserInfo through reflection, and finally executes the ing method in it, because we implement the RowMapper Method for UserInfo.

This eventually calls the public T queryForObject (String SQL, RowMapper RowMapper, Object... args) throws DataAccessException method. And why is the error reported when the above Code can be obtained? after reading the source code, we can find that:

Public T queryForObject (String SQL, Class RequiredType, Object... args) throws DataAccessException this reflection type is to return each data column to the T type, so an error occurs. Therefore, this method only supports this type of data (such as String ), you cannot define Bean entities of complex types. Therefore, you can return a single column (such as count (*) and a column value ).

However, it has not been explained in the document, and I have tested it for a long time. What is the best practice?

 

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.