我想实现从JPA到Spring JDBC的关系。例如,假设我有 Account 和 Advert 对象。根据 JPA,Account 和 Advert 之间的关系是 @OneToMany。
账户类别:
public class Account {
private Long id;
private String username;
private Set<Advert> adverts = new HashSet<Advert>();
// getters + setters
}
广告类:
public class Advert {
private Long id;
private String text;
private Account account;
// getters + setters
}
帐户映射器:
public class AccountMapper implements RowMapper<Account> {
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account = new Account();
account.setId(rs.getLong("id"));
account.setUsername(rs.getString("username"));
return account;
}
}
现在,我正在尝试为 Advert 类创建一个 Mapper。如何将 Advert 类中的 account 变量映射到一行?非常感谢
您可以在不影响应用程序性能的情况下使用 Hibernate,只需查看此 Hibernate 教程,了解数百个与映射实体相关的示例。
对于在 JDBC 中执行此操作,您需要执行以下步骤:
您需要对所有选定的列使用别名,以便 ID 列不会发生冲突。
您可以定义两个行映射器并使用从 Advert 到 Account 的联接并将其传递给 AccountMapper:
public class AdvertMapper implements RowMapper<Advert> {
public Advert mapRow(ResultSet rs, int rowNum) throws SQLException {
Advert advert = new Advert();
advert.setId(rs.getLong("advert_id"));
advert.setText(rs.getString("advert_text"));
return advert;
}
}
public class AccountMapper implements RowMapper<Account> {
private final AdvertMapper advertMapper;
public AccountMapper(AdvertMapper advertMapper) {
this.advertMapper = advertMapper;
}
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account = new Account();
account.setId(rs.getLong("account_id"));
account.setUsername(rs.getString("account_username"));
Advert advert = this.advertMapper.mapRow(rs, rowNum);
advert.setAccount(account);
account.getAdverts().add(advert);
return account;
}
}
AccountMapper
使用AdvertMapper
从连接的数据创建广告。
将此与 Hibernate 进行比较,其中所有这些映射都已为您解析。
如果你不使用 ORM...你就没有对象关系映射!由于这个原因创建了所有 ORM :-)
更严重的是,ORM 使您无需编写大量样板代码。使用直接 JDBC 而不是 JPA 是一种代码优化。与任何其他代码优化一样,应该在适当的时候使用它。它相关于:
我的建议应该是首先使用隐藏在 DAO 层中的 JPA 或本机 hibernate。然后仔细分析你的性能问题,并重写 JDBC 中最昂贵的部分。
当然,你可以直接在 JDBC 中编写 DAO 实现,但是写起来会长很多。
我差点忘记了最重要的部分:在 ORM 中映射类和关系,在 JDBC 中编写独立的 SQL 查询。
解决一对一的情况很容易,正如 Vlad 回答的那样,如果您想将一对多映射为您的帐户 - 广告建议您不能这样做 使用 RowMapper 因为您将尝试将 ResultSet 的多行映射到一个帐户,许多广告。
您也可以手动执行此操作,也可以使用 http://simpleflatmapper.org,它提供从 ResultSet 到 POJO 的映射并提供一对多支持。 请注意,如果您确实想要这些关系,那么双向关系并不好,这是可能的,但它们不会是同一个实例。
结账 http://simpleflatmapper.org/0104-getting-started-springjdbc.html 和 https://arnaudroger.github.io/blog/2017/02/27/jooq-one-to-many.html
您需要获取一个 ResutlSetExtractor - 它是线程安全的,因此只需要一个实例 -
private final ResultSetExtractor<List<Account>> mapper =
JdbcTemplateMapperFactory
.newInstance()
.addKeys("id") // assuming the account id will be on that column
.newResultSetExtractor(Account.class);
// in the method
String query =
"SELECT ac.id as id, ac.username, ad.id as adverts_id, ad.text as adverts_text"
+ "FROM account ac LEFT OUTER JOIN advert ad ON ad.account_id = ac.id order by id "
// the order by id is important here as it uses the break on id on the root object
// to detect new root object creation
List<Account> results = template.query(query, mapper);
这样,您应该会获得一个帐户列表,其中填充了广告列表。但广告不会有帐户。