66import org .slf4j .LoggerFactory ;
77import org .springframework .beans .factory .annotation .Autowired ;
88import org .springframework .jdbc .core .BeanPropertyRowMapper ;
9+ import org .springframework .jdbc .core .JdbcTemplate ;
910import org .springframework .jdbc .core .RowMapper ;
1011import org .springframework .jdbc .core .namedparam .MapSqlParameterSource ;
1112import org .springframework .jdbc .core .namedparam .NamedParameterJdbcTemplate ;
12- import org .springframework .jdbc .support .GeneratedKeyHolder ;
13- import org .springframework .jdbc .support .KeyHolder ;
13+ import org .springframework .jdbc .core .simple .SimpleJdbcInsert ;
1414import org .springframework .stereotype .Repository ;
1515
1616import java .math .BigDecimal ;
@@ -28,10 +28,21 @@ public class JDBCDataRepositoryImpl implements DataRepository {
2828
2929 private final NamedParameterJdbcTemplate jdbcTemplate ;
3030
31+ // NOTE: I would recommend to handle creation and caching of SimpleJdbcInsert instances like depicted here, for two reasons:
32+ // 1. In order to SimpleJdbcInsert to be effective, it cannot be created for each call - remember that during first use of
33+ // SimpleJdbcInsert, metadata for the table are fetched from database and this costs some time. So best way how to use SimpleJdbcInsert
34+ // is to reuse single instance.
35+ // 2. I wouldn't put instances of SimpleJdbcInsert to some external cache, but, like here, tie the instance of SimpleJdbcInsert with DAO bean.
36+ // That way it's ensured, that when the DAO bean is recreated so are be recreated all SimpleJdbcInsert instances the DAO bean depends on...
37+ private final SimpleJdbcInsert insertIntoProject ;
38+
3139 @ SuppressWarnings ("SpringJavaAutowiringInspection" )
3240 @ Autowired
3341 public JDBCDataRepositoryImpl (NamedParameterJdbcTemplate jdbcTemplate ) {
3442 this .jdbcTemplate = jdbcTemplate ;
43+ this .insertIntoProject = new SimpleJdbcInsert ((JdbcTemplate ) jdbcTemplate .getJdbcOperations ())
44+ .withTableName ("project" )
45+ .usingGeneratedKeyColumns ("pid" );
3546 }
3647
3748 @ Override
@@ -120,37 +131,26 @@ public List<Employee> employeesWithSalaryGreaterThan(Integer minSalary) {
120131
121132 @ Override
122133 public Integer insertProject (Project project ) {
123- logger .info ("Inserting project using JDBCTemplate" );
124-
125- String insertStatement = " INSERT INTO project (name, datestarted) " +
126- " VALUES (:name, :datestarted)" ;
127-
128134 MapSqlParameterSource params = new MapSqlParameterSource ()
129135 .addValue ("name" , project .getName ())
130136 .addValue ("datestarted" , project .getDate ());
131137
132- KeyHolder generatedKey = new GeneratedKeyHolder ();
133-
134- jdbcTemplate .update (insertStatement , params , generatedKey );
135-
136- return (Integer ) generatedKey .getKeys ().get ("pid" );
138+ return insertIntoProject .executeAndReturnKey (params ).intValue ();
137139 }
138140
139141 @ Override
140142 public List <Integer > insertProjects (List <Project > projects ) {
141- logger .info ("Batch inserting projects using JDBCTemplate" );
142-
143- String insertStatement = " INSERT INTO project (name, datestarted) " +
144- " VALUES (:name, :datestarted)" ;
145-
146143 MapSqlParameterSource [] paramsList = projects
147144 .stream ()
148145 .map (project -> new MapSqlParameterSource ()
149146 .addValue ("name" , project .getName ())
150147 .addValue ("datestarted" , project .getDate ()))
151148 .toArray (MapSqlParameterSource []::new );
152149
153- jdbcTemplate .batchUpdate (insertStatement , paramsList );
150+ // NOTE: Here we used SimpleJdbcInsert to insert the rows, but you can also use more traditional way
151+ // by specifying the statment to be executed (handy when you need to do some customizations of the statement).
152+ // See insertDepartments() method for an example.
153+ insertIntoProject .executeBatch (paramsList );
154154
155155 // FIXME JDBCTemplate cannot return IDs for every row after batch update!!
156156 return null ;
0 commit comments