Jackson 的 ObjectMapper 和 SQL 中的 RowMapper

mat*_*th5 5 java json jackson spring-boot

我们正在使用对象映射器。当将 ObjectMapper 与 RowMapper 一起使用时,是否应该在每个 mapRow 内部(如下所示)声明它,还是在 mapRow 外部声明为类公共成员?我认为根据本文,它应该作为公共类成员在外部。我应该将 Jackson 的 ObjectMapper 声明为静态字段吗?

目前使用 Spring boot 和 SQL Server 数据库。研究数千/数百万 SQL 行的线程安全性。

List<Product> productList =  namedParameterJdbcTemplate.query(sqlQuery,
        parameters,
        new ProductMapper(productRequest));


public class ProductMapper implements RowMapper<Product> {
    
    @Override
    public Product mapRow(ResultSet rs, int rowNum) throws SQLException {

        ObjectMapper objectMapper = new ObjectMapper()

        Product product = new Product();

        product.setProductId(rs.getLong("ProductId"));
        product.setProductType(rs.getString("ProductType"));
        product.setLocations(objectMapper.readValue(rs.getString("Locations"), new TypeReference<List<ServiceLocation>>(){}));
            } catch (Exception e) {
                throw new ServiceException(e);
            }
        }
Run Code Online (Sandbox Code Playgroud)

注意:请不要问我们为什么要使用 ObjectMapper 编写这个手动映射器,我们正在做遗留编码,并且架构师要求这样做。

Oli*_*ier 3

实例ObjectMapper不是不可变的,但是,如文档中所述:

如果实例的所有配置发生在任何读取或写入调用之前,则映射器实例是完全线程安全的。

这意味着这段代码是完全线程安全的:

public class ProductMapper implements RowMapper<Product> {
    private ObjectMapper mapper;

    public ProductMapper()
    {
        objectMapper = new ObjectMapper();
    }

    @Override
    public Product mapRow(ResultSet rs, int rowNum) throws SQLException {
        Product product = new Product();
        product.setLocations(objectMapper.readValue(rs.getString("Locations"), new TypeReference<List<ServiceLocation>>(){}));
        return product;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,TypeReference仍然为每一行创建对象,效率不是很高。ObjectReader 更好的方法是通过以下方法创建实例readerFor()

public class ProductMapper implements RowMapper<Product> {
    private ObjectReader objectReader;

    public ProductMapper()
    {
        ObjectMapper objectMapper = new ObjectMapper();
        objectReader = objectMapper.readerFor(new TypeReference<List<ServiceLocation>>(){});
    }

    @Override
    public Product mapRow(ResultSet rs, int rowNum) throws SQLException {
        Product product = new Product();
        product.setLocations(objectReader.readValue(rs.getString("Locations")));
        return product;
    }
}
Run Code Online (Sandbox Code Playgroud)

实例ObjectReader是不可变的且线程安全的。