如何在Spring JDBC中创建对象之间的关系?

问题描述 投票:0回答:3

我想实现从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 变量映射到一行?非常感谢

java spring hibernate jpa jdbc
3个回答
8
投票

您可以在不影响应用程序性能的情况下使用 Hibernate,只需查看此 Hibernate 教程,了解数百个与映射实体相关的示例。

对于在 JDBC 中执行此操作,您需要执行以下步骤:

  1. 您需要对所有选定的列使用别名,以便 ID 列不会发生冲突。

  2. 您可以定义两个行映射器并使用从 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 进行比较,其中所有这些映射都已为您解析。


7
投票

如果你不使用 ORM...你就没有对象关系映射!由于这个原因创建了所有 ORM :-)

更严重的是,ORM 使您无需编写大量样板代码。使用直接 JDBC 而不是 JPA 是一种代码优化。与任何其他代码优化一样,应该在适当的时候使用它。它相关于:

  • 使用一些不想依赖 ORM 的表的库(例如:Spring Security 中的用户、角色和 ACL)
  • 发现大型应用程序中的瓶颈

我的建议应该是首先使用隐藏在 DAO 层中的 JPA 或本机 hibernate。然后仔细分析你的性能问题,并重写 JDBC 中最昂贵的部分。

当然,你可以直接在 JDBC 中编写 DAO 实现,但是写起来会长很多。

我差点忘记了最重要的部分:在 ORM 中映射类和关系,在 JDBC 中编写独立的 SQL 查询。


1
投票

解决一对一的情况很容易,正如 Vlad 回答的那样,如果您想将一对多映射为您的帐户 - 广告建议您不能这样做 使用 RowMapper 因为您将尝试将 ResultSet 的多行映射到一个帐户,许多广告。

您也可以手动执行此操作,也可以使用 http://simpleflatmapper.org,它提供从 ResultSet 到 POJO 的映射并提供一对多支持。 请注意,如果您确实想要这些关系,那么双向关系并不好,这是可能的,但它们不会是同一个实例。

结账 http://simpleflatmapper.org/0104-getting-started-springjdbc.htmlhttps://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);

这样,您应该会获得一个帐户列表,其中填充了广告列表。但广告不会有帐户。

© www.soinside.com 2019 - 2024. All rights reserved.