jpa多对多 - 极悦
专注Java教育14年 全国咨询/投诉热线:444-1124-454
极悦LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 jpa多对多的映射实例

jpa多对多的映射实例

更新时间:2022-12-27 16:53:20 来源:极悦 浏览769次

实体Player:玩家。

实体Game:游戏。

玩家和游戏是多对多的关系。一个玩家可以玩很多的游戏,一个游戏也可以被很多玩家玩。

JPA中使用@ManyToMany来注解多对多的关系,由一个关联表来维护。这个关联表的表名默认是:主表名+下划线+从表名。(主表是指关系维护端对应的表,从表指关系被维护端对应的表)。这个关联表只有两个外键字段,分别指向主表ID和从表ID。字段的名称默认为:主表名+下划线+主表中的主键列名,从表名+下划线+从表中的主键列名。

需要注意的:

1、多对多关系中一般不设置级联保存、级联删除、级联更新等操作。

2、可以随意指定一方为关系维护端,在这个例子中,我指定Player为关系维护端,所以生成的关联表名称为: player_game,关联表的字段为:player_id和game_id。

3、多对多关系的绑定由关系维护端来完成,即由Player.setGames(games)来绑定多对多的关系。关系被维护端不能绑定关系,即Game不能绑定关系。

4、多对多关系的解除由关系维护端来完成,即由Player.getGames().remove(game)来解除多对多的关系。关系被维护端不能解除关系,即Game不能解除关系。

5、如果Player和Game已经绑定了多对多的关系,那么不能直接删除Game,需要由Player解除关系后,才能删除Game。但是可以直接删除Player,因为Player是关系维护端,删除Player时,会先解除Player和Game的关系,再删除Player。

Player.java如下:

package com.cndatacom.jpa.entity;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
 
 
/**
 * 玩家
 * @author Luxh
 */
@Entity
@Table(name="player")
public class Player {
     
    @Id
    @GeneratedValue
    private Long id;
     
    /**玩家姓名*/
    @Column(length=32)
    private String name;
     
     
    /**玩家玩的游戏*/
    @ManyToMany
    @JoinTable(name="player_game",joinColumns=@JoinColumn(name="player_id"),
                    inverseJoinColumns=@JoinColumn(name="game_id"))
    //关系维护端,负责多对多关系的绑定和解除
    //@JoinTable注解的name属性指定关联表的名字,joinColumns指定外键的名字,关联到关系维护端(Player)
    //inverseJoinColumns指定外键的名字,要关联的关系被维护端(Game)
    //其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
    //即表名为player_game
    //关联到主表的外键名:主表名+下划线+主表中的主键列名,即player_id
    //关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,即game_id
    //主表就是关系维护端对应的表,从表就是关系被维护端对应的表
    private Set<Game> games = new HashSet<Game>();
 
 
    public Long getId() {
        return id;
    }
 
 
    public void setId(Long id) {
        this.id = id;
    }
 
 
    public String getName() {
        return name;
    }
 
 
    public void setName(String name) {
        this.name = name;
    }
 
 
    public Set<Game> getGames() {
        return games;
    }
 
 
    public void setGames(Set<Game> games) {
        this.games = games;
    }
     
}

Game.java如下:

package com.cndatacom.jpa.entity;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
 
 
/**
 * 游戏
 * @author Luxh
 */
 
@Entity
@Table(name="game")
public class Game {
     
    @Id
    @GeneratedValue
    private Long id;
     
    /**游戏名称*/
    @Column(length=32)
    private String name;
     
    /**游戏拥有的玩家*/
    @ManyToMany(mappedBy="games")
    //只需要设置mappedBy="games"表明Game实体是关系被维护端就可以了
    //级联保存、级联删除等之类的属性在多对多关系中是不需要设置
    //不能说删了游戏,把玩家也删掉,玩家还可以玩其他的游戏
    private Set<Player> players = new HashSet<Player>();
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Set<Player> getPlayers() {
        return players;
    }
 
    public void setPlayers(Set<Player> players) {
        this.players = players;
    }
     
     
}

简单的测试如下:

package com.cndatacom.jpa.test;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import com.cndatacom.jpa.entity.Game;
import com.cndatacom.jpa.entity.Player;
 
public class TestManyToMany {
     
EntityManagerFactory emf = null;
     
    @Before
    public void before() {
        //根据在persistence.xml中配置的persistence-unit name 创建EntityManagerFactory
        emf = Persistence.createEntityManagerFactory("myJPA");
    }
     
    @After
    public void after() {
        //关闭EntityManagerFactory
        if(null != emf) {
            emf.close();
        }
    }
     
    /**
     * 创建玩家和游戏
     */
    @Test
    public void testSavePlayerAndGame() {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        //因为Player和Game之间没有级联保存的关系,所以Playe和Game要分别保存
         
        Player player = new Player();
        player.setName("西门吹雪");
        //保存Player
        em.persist(player);
         
        Game game = new Game();
        game.setName("大菠萝3");
        //保存game
        em.persist(game);
         
        em.getTransaction().commit();
        em.close();
    }
     
    /**
     * 给玩家添加游戏
     */
    @Test
    public void testAddGameToPlayer() {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        //找出ID为1的玩家
        Player player = em.find(Player.class, 1L);
        //找出ID为1的游戏
        Game game = em.find(Game.class, 1L);
         
        Set<Game> games = new HashSet<Game>();
        games.add(game);
         
        //因为Player是关系的维护端,所以必须由Player来添加关系
        player.setGames(games);
         
        em.getTransaction().commit();
        em.close();
    }
     
    /**
     * 玩家删除游戏
     */
    @Test
    public void testRemoveGameFormPlayer() {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        //找出ID为1的玩家
        Player player = em.find(Player.class, 1L);
        //找出ID为1的游戏
        Game game = em.find(Game.class, 1L);
         
        //因为Player是关系维护端,所以关系的解除由Player来完成
        player.getGames().remove(game);
        em.getTransaction().commit();
        em.close();
    }
}

生成的关联表结构如下:

jpa多对多

以上就是极悦小编介绍的"jpa多对多的映射实例",希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为您务。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>