当前位置: 首页 > article >正文

深入解析JPA中的多对多关系映射

在Java持久化API(JPA)中,多对多关系是一种常见的数据模型。它描述了两个实体之间可以相互关联多次的关系。例如,一个学生可以参加多个课程,而一个课程也可以有多个学生。这种关系的实现和管理在JPA中有着明确的规范和实现方式。
一、多对多关系的基本概念
在多对多关系中,一个JPA实体会包含另一个实体的集合引用。具体来说,包含集合引用的实体被称为“源实体”(source entity),而被引用的实体被称为“目标实体”(target entity)。为了将这种多对多关系映射到数据库表中,我们通常使用@ManyToMany注解来标记源实体中的集合属性。
二、多对多关系的数据库映射
多对多关系在数据库中是通过一个中间的“连接表”(join table)来实现的。这个连接表包含两个外键列,分别指向源实体表和目标实体表。由于连接表中没有唯一性约束,因此可以实现多对多的关系,即一个源实体可以关联多个目标实体,反之亦然。
三、自定义连接表
在某些情况下,我们可能需要使用自定义的连接表,或者需要映射一个已经存在的连接表。这时可以使用@JoinTable注解来指定连接表的名称、外键列的名称等属性。
四、实例演示
以下是一个具体的代码示例,展示如何在JPA中实现多对多关系。
实体类定义
java复制
@Entity
public class EntityA {
@Id
@GeneratedValue
private int myIdA;

@ManyToMany
private List<EntityB> entityBList;

// 省略getter和setter方法

}

@Entity
public class EntityB {
@Id
@GeneratedValue
private int myIdB;

private String str;

// 省略getter和setter方法

}
主程序
java复制
public class ExampleMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“test”);
try {
persistEntity(emf);
nativeQueries(emf);
loadEntityA(emf);
loadEntityB(emf);
} finally {
emf.close();
}
}

private static void nativeQueries(EntityManagerFactory emf) {
    System.out.println(" --- native queries");
    EntityManager em = emf.createEntityManager();
    nativeQuery(em, "Select * from EntityA");
    nativeQuery(em, "Select * from EntityB");
    nativeQuery(em, "Select * from ENTITYA_ENTITYB");
}

private static void persistEntity(EntityManagerFactory emf) {
    System.out.println("-- Persisting entities --");
    EntityManager em = emf.createEntityManager();
    EntityB entityB = new EntityB();
    entityB.setStr("testStringB");
    EntityB entityB2 = new EntityB();
    entityB2.setStr("testStringB 2");
    EntityA entityA = new EntityA();
    entityA.setEntityBList(Arrays.asList(entityB, entityB2, entityB));
    EntityA entityA2 = new EntityA();
    entityA2.setEntityBList(Arrays.asList(entityB, entityB2));
    em.getTransaction().begin();
    em.persist(entityA);
    em.persist(entityA2);
    em.persist(entityB);
    em.persist(entityB2);
    em.getTransaction().commit();
    em.close();
}

private static void loadEntityA(EntityManagerFactory emf) {
    System.out.println("-- Loading EntityA --");
    EntityManager em = emf.createEntityManager();
    List<EntityA> entityAList = em.createQuery("Select t from EntityA t").getResultList();
    entityAList.forEach(System.out::println);
    em.close();
}

private static void loadEntityB(EntityManagerFactory emf) {
    System.out.println("-- Loading EntityB --");
    EntityManager em = emf.createEntityManager();
    List<EntityB> entityBList = em.createQuery("Select t from EntityB t").getResultList();
    entityBList.forEach(System.out::println);
    em.close();
}

public static void nativeQuery(EntityManager em, String s) {
    System.out.printf("---------------------------%n'%s'%n", s);
    Query query = em.createNativeQuery(s);
    List list = query.getResultList();
    for (Object o : list) {
        if(o instanceof Object[]) {
            System.out.println(Arrays.toString((Object[]) o));
        }else{
            System.out.println(o);
        }
    }
}

}
五、输出结果
运行上述程序后,我们可以看到以下输出:
数据库表结构
plaintext复制

‘SHOW TABLES’
[ENTITYA, PUBLIC]
[ENTITYA_ENTITYB, PUBLIC]
[ENTITYB, PUBLIC]

‘SHOW COLUMNS from EntityA’
[MYIDA, INTEGER(10), NO, PRI, NULL]

‘SHOW COLUMNS from EntityB’
[MYIDB, INTEGER(10), NO, PRI, NULL]
[STR, VARCHAR(255), YES


http://www.kler.cn/a/525782.html

相关文章:

  • Java 知识速记:全面解析 final 关键字
  • Redis学习之哨兵二
  • sem_init的概念和使用案例
  • Git进阶之旅:Git 配置信息 Config
  • Android车机DIY开发之学习篇(七)NDK交叉工具构建
  • 【C++】特殊类设计、单例模式与类型转换
  • Java---猜数字游戏
  • wordpress每隔24小时 随机推荐一个指定分类下的置顶内容。
  • 【Elasticsearch 】自定义分词器
  • Pyside6(PyQT5)的QSqlQueryModel的常用方法
  • 【C语言】main函数解析
  • 上位机知识篇---GitGitHub
  • 在MIMIC IV数据库的derived中有bg、chemistry和vitalsign,它们都有Glucose指标,如何区分?
  • C++并发编程指南06
  • 基于springboot的校园部门资料管理系统
  • 搜索引擎快速收录:关键词布局的艺术
  • DeepSeek回答人不会干出超出视角之外的事
  • 高速PCB设计指南4——叠层设计与PCB技术
  • 【CS61A 2024秋】Python入门课,全过程记录P4(Week7 Generators开始,更新于2025/1/30)
  • 使用langchain ollama gradio搭建一个本地基于deepseek r1的RAG问答系统
  • C28.【C++ Cont】顺序表的实现
  • 详细解释java当中的所有知识点(前言及数据类型及变量)(第一部分)
  • 《攻克语言密码:教AI理解隐喻与象征》
  • Airflow:深入理解Apache Airflow 调度器
  • Github 2025-01-30 Go开源项目日报 Top10
  • Linux下多线程编程