Spring Data JDBC Extensions - Core JDBC Extensions (扩展Spring特性的支持类)

Part I Core JDBC Extensions

1 扩展Spring特性的一些支持类

Spring 框架中JDBC支持是很好,但是时不时有一些功能看起来有用可是不包含在框架中。Spring Data JDBC Extensions 项目为这些类型的扩展提供了一个 “Home”。
1.1 一对多关系映射
我们常常会在我们的数据库项目中使用一对多的关系型映射。一个顾客会有多个地址,一个订单可能会包含多项等等。我们现在提供一个ResultSetExtractor 实现来处理这些公共的工作。
让我们来看看下面定义好的数据库结构
CREATE TABLE customer(
  id BIGINT IDENTITY PRIMARY KEY, 
  name VARCHAR(255));
CREATE TABLE address (
  id BIGINT IDENTITY PRIMARY KEY, 
  customer_id BIGINT CONSTRAINT address_customer_ref 
    FOREIGN KEY REFERENCES customer (id), 
  street VARCHAR(255), 
  city VARCHAR(255));
上面两张表是通过一个外键约束关联起来的。在具体实现类 - Customer 和Address 中, Customer 将有一个Address集合来映射这种关系。
public class Customer {

  private Integer id;

  private String name;

  private Set<Address> addresses = new HashSet<Address>();

  public Set<Address> getAddresses() {
    return addresses;
  }

  public void addAddress(Address address) {
    this.addresses.add(address);
  }

// other setters and getters

}

public class Address {

  private Integer id;

  private String street;

  private String city;

// setters and getters

}

执行下面查询语句,对于每个Customer 可能会有多条记录返回。
List<Customer> result = template.query(
  "select customer.id, customer.name, address.id, " +
    "address.customer_id, address.street, address.city " +
    "from customer " +
    "left join address on customer.id = address.customer_id " +
    "order by customer.id",
  resultSetExtractor);
为了能够获得多行记录,我们通过继承OneToManyResultSetExtractor来创建一个新的类CustomerAddressExtractor。 通过root class(Customer), child class(Address)以及主外键来参数化OneToManyResultSetExtractor。
public class CustomerAddressExtractor extends
    OneToManyResultSetExtractor<Customer, Address, Integer> {

  public CustomerAddressExtractor() {
    super(new CustomerMapper(), new AddressMapper());
  }

  @Override
  protected Integer mapPrimaryKey(ResultSet rs) throws SQLException {
    return rs.getInt("customer.id");
  }

  @Override
  protected Integer mapForeignKey(ResultSet rs) throws SQLException {
    if (rs.getObject("address.customer_id") == null) {
      return null;
    }
    else {
      return rs.getInt("address.customer_id");
    }
  }

  @Override
  protected void addChild(Customer root, Address child) {
    root.addAddress(child);
  }
}
我们需要一种方式来匹配Customer的主键与Address的外键。因此我们使用一种抽象的方法mapPrimaryKey 和mapForeignKey来映射这种关系。我们必须考虑对于Customer他的地址可能不存在,所以Customer 外键可能为空。我们同样需要把Address 对象映射到Customer中。通过实现一个抽象的方法addChild,可以在Customer 类中调用Address。
在CustomerAddressExtractor的构造方法中,我们调用父类构造方法为Customer 和 Address 实现RowMapper接口。 在本例中,这些标准的标准的RowMappers是通过内部类方式来实现的。

private static class CustomerMapper implements RowMapper<Customer> {

  public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
    Customer c = new Customer();
    c.setId(rs.getInt("customer.id"));
    c.setName(rs.getString("customer.name"));
    return c;
  }
}

private static class AddressMapper implements RowMapper<Address> {

  public Address mapRow(ResultSet rs, int rowNum) throws SQLException {
    Address a = new Address();
    a.setId(rs.getInt("address.id"));
    a.setStreet(rs.getString("address.street"));
    a.setCity(rs.getString("address.city"));
    return a;
  }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值