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

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

内容简介:正确合并集合并不是一件容易的事!推荐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中如何合并实体集合?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

计算机程序设计艺术:第4卷 第4册(双语版)

计算机程序设计艺术:第4卷 第4册(双语版)

Donald E.Knuth / 苏运霖 / 机械工业出版社 / 2007-4 / 42.00元

关于算法分析的这多卷论著已经长期被公认为经典计算机科学的定义性描述。迄今已出版的完整的三卷组成了程序设计理论和实践的惟一的珍贵源泉,无数读者都赞扬Knuth的著作对个人的深远影响。科学家们为他的分析的美丽和优雅所惊叹,而从事实践的程序员们已经成功地应用他的“菜谱式”的解到日常问题上,所有人都由于Knuth在书中所表现出的博学、清晰、精确和高度幽默而对他无比敬仰。   为开始后续各卷的写作并更......一起来看看 《计算机程序设计艺术:第4卷 第4册(双语版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具