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

时间:2014-08-13 07:51:12

标签: java spring hibernate jpa jdbc

我想实现从JPA到Spring JDBC的关系。例如,假设我有Account和Advert对象。根据JPA,帐户和广告之间的关系是 @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
}

AccountMapper:

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。如何将广告类中的帐户变量映射到行?非常感谢

3 个答案:

答案 0 :(得分:5)

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

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

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

  2. 您可以定义两个行映射器并使用从广告到帐户的连接并将其传递给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;
        }
    }
    
  3. AccountMapper使用AdvertMapper根据已加入的数据创建广告。

    将此与Hibernate进行比较,其中所有这些映射都已为您解决。

答案 1 :(得分:4)

好吧,如果你不使用ORM ......你没有对象关系映射!在创建所有ORM之后: - )

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

  • 使用少量不想依赖ORM的表的库(例如:spring安全性中的用户,角色和ACL)
  • 确定了较大应用程序中的瓶颈

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

当然,您可以直接在JDBC中编写DAO实现代码,但写入时间会更长。

我几乎忘记了基本部分:在ORM中映射类和关系,在JDBC中编写独立的SQL查询。

答案 2 :(得分:1)

解决一对一案件很容易就像弗拉德回答的那样,如果你想将一个到多个地图作为你的账户 - 广告建议你做不到 使用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);

你应该得到一个帐户列表,其中填写了广告列表。但是广告没有帐户。