谁能在hibernate中解释mappedBy?

时间:2012-02-02 06:46:31

标签: java hibernate java-ee hibernate-mapping

我是hibernate的新手,需要使用一对多和多对一的关系。它是我对象中的双向关系,因此我可以从任一方向遍历。 mappedBy是推荐的方法,但我无法理解。有人可以解释一下:

  • 使用它的推荐方法是什么?
  • 它解决了什么目的?

为了我的例子,这里是带注释的类:

  • Airline OWNS很多 AirlineFlights
  • 许多 AirlineFlights属于 ONE Airline

航空公司

@Entity 
@Table(name="Airline")
public class Airline {
    private Integer idAirline;
    private String name;

    private String code;

    private String aliasName;
    private Set<AirlineFlight> airlineFlights = new HashSet<AirlineFlight>(0);

    public Airline(){}

    public Airline(String name, String code, String aliasName, Set<AirlineFlight> flights) {
        setName(name);
        setCode(code);
        setAliasName(aliasName);
        setAirlineFlights(flights);
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="IDAIRLINE", nullable=false)
    public Integer getIdAirline() {
        return idAirline;
    }

    private void setIdAirline(Integer idAirline) {
        this.idAirline = idAirline;
    }

    @Column(name="NAME", nullable=false)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = DAOUtil.convertToDBString(name);
    }

    @Column(name="CODE", nullable=false, length=3)
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = DAOUtil.convertToDBString(code);
    }

    @Column(name="ALIAS", nullable=true)
    public String getAliasName() {
        return aliasName;
    }
    public void setAliasName(String aliasName) {
        if(aliasName != null)
            this.aliasName = DAOUtil.convertToDBString(aliasName);
    }

    @OneToMany(fetch=FetchType.LAZY, cascade = {CascadeType.ALL})
    @JoinColumn(name="IDAIRLINE")
    public Set<AirlineFlight> getAirlineFlights() {
        return airlineFlights;
    }

    public void setAirlineFlights(Set<AirlineFlight> flights) {
        this.airlineFlights = flights;
    }
}

AirlineFlights:

@Entity
@Table(name="AirlineFlight")
public class AirlineFlight {
    private Integer idAirlineFlight;
    private Airline airline;
    private String flightNumber;

    public AirlineFlight(){}

    public AirlineFlight(Airline airline, String flightNumber) {
        setAirline(airline);
        setFlightNumber(flightNumber);
    }

    @Id
    @GeneratedValue(generator="identity")
    @GenericGenerator(name="identity", strategy="identity")
    @Column(name="IDAIRLINEFLIGHT", nullable=false)
    public Integer getIdAirlineFlight() {
        return idAirlineFlight;
    }
    private void setIdAirlineFlight(Integer idAirlineFlight) {
        this.idAirlineFlight = idAirlineFlight;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="IDAIRLINE", nullable=false)
    public Airline getAirline() {
        return airline;
    }
    public void setAirline(Airline airline) {
        this.airline = airline;
    }

    @Column(name="FLIGHTNUMBER", nullable=false)
    public String getFlightNumber() {
        return flightNumber;
    }
    public void setFlightNumber(String flightNumber) {
        this.flightNumber = DAOUtil.convertToDBString(flightNumber);
    }
}

修改

数据库架构:

AirlineFlights的idAirline为ForeignKey,航空公司没有idAirlineFlights。这使得AirlineFlights成为所有者/识别实体?

理论上,我希望航空公司成为航空公司的所有者。

enter image description here

7 个答案:

答案 0 :(得分:259)

MappedBy信号休眠,关系的关键在另一边。

这意味着虽然您将两个表链接在一起,但这些表中只有一个对另一个表有外键约束。 MappedBy允许您仍然从不包含约束的表链接到另一个表。

答案 1 :(得分:134)

通过在两个模型上指定@JoinColumn,您没有双向关系。你有两个单向关系,并且有一个非常令人困惑的映射。你告诉两个模型他们“拥有”IDAIRLINE专栏。实际上只有其中一个真的应该! “正常”的做法是完全取消@JoinColumn一侧的@OneToMany,而是将mappedBy添加到@OneToMany

@OneToMany(cascade = CascadeType.ALL, mappedBy="airline")
public Set<AirlineFlight> getAirlineFlights() {
    return airlineFlights;
}

告诉Hibernate“在我找到配置的东西上查看名为'airline'的bean属性。”

答案 2 :(得分:16)

mappedby说明了一切,它告诉hibernate不要映射这个字段。它已经被这个字段映射[name =&#34; field&#34;] field位于另一个实体(name of the variable in the class not the table in the database) ..

  

如果你不这样做,hibernate将映射这两个关系,因为它不是   相同的关系

所以我们需要告诉hibernate只在一侧进行映射并在它们之间进行协调。

答案 3 :(得分:15)

表关系与实体关系

在关系数据库系统中,one-to-many table relationship如下所示:

<code>one-to-many</code> table relationship

请注意,该关系基于子表中的外键列(例如post_id)。

因此,在管理one-to-many表关系时,只有一个事实来源。

现在,如果您采用的双向实体关系映射到我们之前见过的one-to-many表关系:

Bidirectional <code>One-To-Many</code> entity association

看看上面的图,您会发现有两种方法可以管理这种关系。

Post实体中,您拥有comments集合:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

并且,在PostComment中,post关联被映射如下:

@ManyToOne(
    fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;

因为有两种表示外键列的方法,所以在将关联状态更改转换为其等效的外键列值修改时,必须定义哪个是真相的来源。

MappedBy

mappedBy属性告诉@ManyToOne端负责管理外键列,并且该集合仅用于获取子实体并将父实体状态更改级联为子实体(例如,删除父实体也应该删除子实体。

同步双向关联的两端

现在,即使您定义了mappedBy属性,并且子端@ManyToOne关联管理“外键”列,您仍然需要同步双向关联的两端。

做到这一点的最佳方法是添加以下两个实用程序方法:

public void addComment(PostComment comment) {
    comments.add(comment);
    comment.setPost(this);
}

public void removeComment(PostComment comment) {
    comments.remove(comment);
    comment.setPost(null);
}

addCommentremoveComment方法可确保双方同步。因此,如果我们添加一个子实体,则该子实体需要指向父实体,并且该父实体应在子集合中包含该子实体。

有关同步所有双向实体关联类型的最佳方法的更多详细信息,请查看this article

答案 4 :(得分:10)

mappedby =&#34;在另一个类中创建的同一类实体的对象“

注意:-Mapped只能在一个类中使用,因为一个表必须包含外键约束。如果映射的可以应用于两侧,那么它从两个表中删除外键而没有外键与b / w两个表没有关系。

注意: - 它可用于以下注释: - 1. @ OneTone 2. @一对多 3. @多对多

注意---它不能用于以下注释: - 1. @多对一

一对一: - 在映射的任何一侧执行,但仅在一侧执行。 它将删除应用它的类的表上的额外外键约束列。

例如。如果我们在员工对象的Employee类中应用映射,那么将删除Employee表中的外键。

答案 5 :(得分:1)

mappedBy 属性表征双向关联,必须在父端设置。换句话说,对于双向@OneToMany 关联,在父端将mappedBy 设置为@OneToMany,并在mappedBy 引用的子端添加@ManyToOne。通过mappedBy,双向@OneToMany 关联表明它反映了@ManyToOne 子端映射。

答案 6 :(得分:0)

您开始使用ManyToOne映射,然后将BiTirectMany映射也用于BiDirectional方式。 然后在OneToMany端(通常是您的父表/类),您必须提到“mappedBy”(映射由子表/类中完成),因此hibernate不会在DB中创建EXTRA映射表(如TableName = parent_child)。