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

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

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

查看所有标签

猜你喜欢:

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

Music Recommendation and Discovery

Music Recommendation and Discovery

Òscar Celma / Springer / 2010-9-7 / USD 49.95

With so much more music available these days, traditional ways of finding music have diminished. Today radio shows are often programmed by large corporations that create playlists drawn from a limited......一起来看看 《Music Recommendation and Discovery》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换