javaspring-bootrowmapper

Should BeanPropertyRowMapper be singleton or declared in each query?


I am using BeanPropertyRowMapper. Should BeanPropertyRowMapper be called for every JdbcTemplate query, be a prototype, or a singleton in the application? My application has multithreading requests also for get, post, put requests.

Map<String, Object> params = new HashMap<>();
params.put("customerId", customerId);

String findByCustomerIdSql = """ 
    SELECT firstName, employeeId, feeAmount, enrollmentDate, activeFlag 
    FROM dbo.customer 
    WHERE customer_Id = :customerId
""";

try {
    CustomerGetResponse customerGetResponse = namedJdbcTemplate.queryForObject(findByCustomerIdSql,
            params, BeanPropertyRowMapper.newInstance(CustomerGetResponse.class));
    return customerGetResponse;

Similar to this question: Singleton vs prototype JdbcTemplate


Solution

  • It can be used as a singleton. You can check the source code for this class - there is no common mutable state in the class, all of the fields are initialized once during an instance creation and then they are read-only. Therefore mapRow() method implementation here is thread-safe. So you should be good.

    P.S: in our code base we do something like this:

    @Bean
    BeanPropertyRowMapper<FirstEntity> firstEntityRowMapper() {
        return new BeanPropertyRowMapper<>(FirstEntity.class);
    }
    
    @Bean
    BeanPropertyRowMapper<SecondEntity> secondEntityRowMapper() {
        return new BeanPropertyRowMapper<>(SecondEntity.class);
    }
    

    And then just do this:

    @Autowired
    BeanPropertyRowMapper<FirstEntity> firstEntityRowMapper;
    
    // And in the method
    
    jdbcTemplate.query("SELECT ...", firstEntityRowMapper);
    

    Note: BeanPropertyRowMapper is responsible for mapping only instances of one particular entity. If you really care about performance, then you can write your own RowMapper implementation for every entity. This will be faster than BeanPropertyRowMapper, which is there for convenience. Most of the time BeanPropertyRowMapper is what you want, but creating it for every request individually will be too expensive so do not do that.