Hibernate/JPA中如何合并实体集合?

栏目: Hibernate · 发布时间: 7年前

内容简介:正确合并集合并不是一件容易的事!推荐Vlad的例子关键点:假设tournament和tennis_player两个表中有数据:

正确合并集合并不是一件容易的事!推荐Vlad的例子 文章 的Spring Boot示例,只有手工进行集合合并。

关键点:

  • 删除传入集合中不再存在的现有数据库行。
  • 更新现有的可以在传入集合中找到的数据库行。
  • 添加在传入集合中找到的行,这些行在当前数据库快照中是找不到的。

假设tournament和tennis_player两个表中有数据:

INSERT INTO tournament (id, name) VALUES (1, 'Roland Garros');
INSERT INTO tournament (id, name) VALUES (2, 'US Open');
INSERT INTO tennis_player (id, name, tournament_id) VALUES (1, 'Rafael Nadal', 1);
INSERT INTO tennis_player (id, name, tournament_id) VALUES (2, 'Roger Federer', 1);
INSERT INTO tennis_player (id, name, tournament_id) VALUES (3, 'David Ferer', 2);
INSERT INTO tennis_player (id, name, tournament_id) VALUES (4, 'Andy Murray', 2);
INSERT INTO tennis_player (id, name, tournament_id) VALUES (5, 'Del Potro', 2);
INSERT INTO tennis_player (id, name, tournament_id) VALUES (6, 'Novak D', 2);
INSERT INTO tennis_player (id, name, tournament_id) VALUES (7, 'John Isner', 2);

Tournament实体:和TennisPlayer 是双向一对多关系

@Entity
<b>public</b> <b>class</b> Tournament implements Serializable {

    <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    <b>private</b> Long id;

    <b>private</b> String name;

    @OneToMany(cascade = CascadeType.ALL, 
            mappedBy = <font>"tournament"</font><font>, orphanRemoval = <b>true</b>)
    <b>private</b> List<TennisPlayer> tennisPlayers = <b>new</b> ArrayList<>();
</font>

TennisPlayer 实体:

@Entity
<b>public</b> <b>class</b> TennisPlayer implements Serializable {

    <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    <b>private</b> Long id;

    <b>private</b> String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = <font>"tournament_id"</font><font>)
    <b>private</b> Tournament tournament;
</font>

仓储:

@Repository
@Transactional(readOnly = <b>true</b>)
<b>public</b> <b>interface</b> TournamentRepository <b>extends</b> JpaRepository<Tournament, Long> { 
    
    @Query(value=<font>"SELECT t FROM Tournament t JOIN FETCH t.tennisPlayers WHERE t.name = ?1"</font><font>)
    Tournament tournamentAndPlayers(String name);
}

@Repository
@Transactional(readOnly = <b>true</b>)
<b>public</b> <b>interface</b> TennisPlayerRepository <b>extends</b> JpaRepository<TennisPlayer, Long> {

    @Query(value = </font><font>"SELECT p FROM TennisPlayer p JOIN p.tournament t WHERE t.name = ?1"</font><font>)
    List<TennisPlayer> playersOfTournament(String name);
}
</font>

在服务中进行两个实体集合的合并:

@Service
<b>public</b> <b>class</b> TennisService {

    <b>private</b> <b>final</b> TournamentRepository tournamentRepository;
    <b>private</b> <b>final</b> TennisPlayerRepository tennisPlayerRepository;

    <b>public</b> TennisService(TournamentRepository tournamentRepository,
            TennisPlayerRepository tennisPlayerRepository) {

        <b>this</b>.tournamentRepository = tournamentRepository;
        <b>this</b>.tennisPlayerRepository = tennisPlayerRepository;
    }

    <b>public</b> List<TennisPlayer> fetchPlayersOfTournament(String name) {

        <b>return</b> tennisPlayerRepository.playersOfTournament(name);
    }

    @Transactional
    <b>public</b> <b>void</b> updatePlayersOfTorunament(String name, List<TennisPlayer> players) {

        Tournament tournament = tournamentRepository.tournamentAndPlayers(name);
        System.out.println(<font>"-------------------------------------------------"</font><font>);

        </font><font><i>// Remove the existing database rows that are no </i></font><font>
        </font><font><i>// longer found in the incoming collection (players)</i></font><font>
        </font><font><i>//删除传入集合中不再存在的现有数据库行</i></font><font>
        tournament.getTennisPlayers().removeIf((t) -> !players.contains(t));

        </font><font><i>// Update the existing database rows which can be found </i></font><font>
        </font><font><i>// in the incoming collection (players)</i></font><font>
        </font><font><i>//更新现有的可以在传入集合中找到的数据库行</i></font><font>
</font>
        List<TennisPlayer> newPlayers = players.stream()
                .filter((t) -> !tournament.getTennisPlayers().contains(t))
                .collect(Collectors.toList());

        players.stream()
                .filter((t) -> !newPlayers.contains(t))                
                .forEach((t) -> {
                    t.setTournament(tournament);
                    TennisPlayer mergedPlayer = tennisPlayerRepository.save(t);
                    tournament.getTennisPlayers().set(
                            tournament.getTennisPlayers().indexOf(mergedPlayer),
                            mergedPlayer);
                });

        <font><i>// Add the rows found in the incoming collection, </i></font><font>
        </font><font><i>// which cannot be found in the current database snapshot</i></font><font>
        newPlayers.forEach((t) -> tournament.addTennisPlayer(t));
    }

}
</font>

手工合并集合的调用:

 System.out.println(<font>"------------------- Players from US Open --------------------"</font><font>);
            List<TennisPlayer> players = tennisService.fetchPlayersOfTournament(</font><font>"US Open"</font><font>);            
            
            players.forEach((t) -> System.out.println(</font><font>"Us Open: "</font><font> + t.getName() + </font><font>" | id:("</font><font> + t.getId() + </font><font>")"</font><font>));
            
            System.out.println(</font><font>"---------- Players from US Open Updated Detached ------------"</font><font>);
            
            </font><font><i>// ,update first player name</i></font><font>
            players.get(0).setName(</font><font>"Fernando Verdasco"</font><font>);
            
            </font><font><i>// remove second player</i></font><font>
            players.remove(1);
                        
            </font><font><i>// add a new player</i></font><font>
            TennisPlayer player = <b>new</b> TennisPlayer();
            player.setName(</font><font>"Alexander Zverev"</font><font>);
            players.add(player);
            
            players.forEach((t) -> System.out.println(</font><font>"Us Open: "</font><font> + t.getName() + </font><font>" | id:("</font><font> + t.getId() + </font><font>")"</font><font>));
            
            System.out.println(</font><font>"----------------- Players from US Open Merged ----------------"</font><font>);
            tennisService.updatePlayersOfTorunament(</font><font>"Us Open"</font><font>, players);
            
            players.forEach((t) -> System.out.println(</font><font>"Us Open: "</font><font> + t.getName() + </font><font>" | id:("</font><font> + t.getId() + </font><font>")"</font><font>));
</font>

源代码可以在 这里 找到  。


以上所述就是小编给大家介绍的《Hibernate/JPA中如何合并实体集合?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Effective JavaScript

Effective JavaScript

赫尔曼 (David Herman) / 黄博文、喻杨 / 机械工业出版社 / 2014-1-1 / CNY 49.00

Effective 系列丛书经典著作,亚马逊五星级畅销书,Ecma 的JavaScript 标准化委员会著名专家撰写,JavaScript 语言之父、Mozilla CTO —— Brendan Eich 作序鼎力推荐!作者凭借多年标准化委员会工作和实践经验,深刻辨析JavaScript 的内部运作机制、特性、陷阱和编程最佳实践,将它们高度浓缩为极具实践指导意义的 68 条精华建议。 本书共......一起来看看 《Effective JavaScript》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具