java - jpa - 如何创建与 IdClass 的多对多关系?

标签 java hibernate jpa many-to-many

我有 3 个具有多对多关系的表

  • A(id,名称,...)主键id
  • B(id,名称,...),带有主键id
  • AB (id_a, id_b, date, ....) - 关系表, 主键

我可以为 hibernate 类建模,以便使用 IdClass 而不是 EmbeddedId 解决方案(这样我就可以避免使用级联不必要的级别来调用 - getId().getA ())

PS 尝试混合这些解决方案,但不起作用:
http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/
How to map a composite key with Hibernate?

最佳答案

When it comes to building relationships between entities,
the closest wall next to me and my head often join... (Stephan)

以下是实体 A 和 B 之间多对多关系的工作示例:

A.java

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class A {
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    @Column(name="id_a")
    private Integer id;

    private String name;

    @OneToMany(mappedBy="a",cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    private List<AB> abAssociations = new ArrayList<>();

    // Getters and setters...
}

B.java

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class B {
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    @Column(name = "id_b")
    private Integer id;

    private String name;

    @OneToMany(mappedBy = "b", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    private List<AB> abAssociations = new ArrayList<>();

    // Getters and setters...
}

AB.java

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@IdClass(ABid.class)
public class AB {
    @Id
    @ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    private A a;

    @Id
    @ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    private B b;

    @Temporal(TemporalType.TIMESTAMP)
    private Date date;

    // Getters and setters...
}

ABid.java

import java.io.Serializable;

// The IdClass MUST implement Serializable and override #hashCode and #equals
public class ABid implements Serializable {

    private static final long serialVersionUID = -2834827403836993112L;

    private A a;
    private B b;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((a == null) ? 0 : a.hashCode());
        result = prime * result + ((b == null) ? 0 : b.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ABid other = (ABid) obj;
        if (a == null) {
            if (other.a != null)
                return false;
        } else if (!a.equals(other.a))
            return false;
        if (b == null) {
            if (other.b != null)
                return false;
        } else if (!b.equals(other.b))
            return false;
        return true;
    }
}

pom.xml

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>4.3.7.Final</version>
    </dependency>
<小时/>

示例代码

import java.util.Date;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {
    public static void main(String[] args) {
        // * Init entity manager
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("playground");

        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        // * Create two entities and persist them
        // We must persist the entities first alone before we build and flush their relation
        A a = new A();
        a.setName("foo");
        em.persist(a);

        B b = new B();
        b.setName("bar");
        em.persist(b);

        // * Build relationships between the two previous entities
        AB ab = new AB();
        ab.setA(a);
        ab.setB(b);
        ab.setDate(new Date());
        a.getAbAssociations().add(ab);
        b.getAbAssociations().add(ab);

        // * Flush our changements in the database
        em.getTransaction().commit();
        em.close();
        emf.close();
    }
}

这是 Hibernate 在 Postgresql 数据库上创建的表的 SQL 代码。

CREATE TABLE a
(
  id_a integer NOT NULL,
  name character varying(255),
  CONSTRAINT a_pkey PRIMARY KEY (id_a)
)

CREATE TABLE b
(
  id_b integer NOT NULL,
  name character varying(255),
  CONSTRAINT b_pkey PRIMARY KEY (id_b)
)

CREATE TABLE ab
(
  date timestamp without time zone,
  b_id_b integer NOT NULL,
  a_id_a integer NOT NULL,
  CONSTRAINT ab_pkey PRIMARY KEY (a_id_a, b_id_b),
  CONSTRAINT fk_3exna7nsxvj1kv9i9pntmwlf1 FOREIGN KEY (a_id_a)
      REFERENCES a (id_a) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_n3jrq53nr1elew4rytocopkbu FOREIGN KEY (b_id_b)
      REFERENCES b (id_b) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

关于java - jpa - 如何创建与 IdClass 的多对多关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28580043/

相关文章:

java - 如何通过编程方式获取java中的jboss版本?

java - 为什么 double 可以比 long 存储更多的信息? (JAVA)

java - 一遍又一遍地使用相同的 Hibernate Session 是一种好习惯吗

java - Hibernate session 不更新实体

java - QueryDSL 内连接 : path expected for join

java - Hibernate 用户模型不保存用户角色和角色

java - 扩展 Activity 时抽屉导航出现点击问题

java - 如何使实例在我的 Android 应用程序中的任何位置可用或可访问

java - JPA 分页查询在每次后续调用中变慢

java - Spring 无法使用 JPA 保存/更新实体