我对hibernate不熟悉,需要使用一对多和多对一关系。它在我的对象中是一种双向关系,所以我可以从任何一个方向遍历。mappedBy是推荐的方法,但是,我不能理解它。谁能解释一下:

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

为了方便我的例子,下面是带有注释的类:

航空公司拥有许多航班 许多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;
    }
}

航空公司航班:

@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,而Airline没有idAirlineFlights。这使得,AirlineFlights作为所有者/识别实体?

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


MappedBy向hibernate发出信号,表示关系的键在另一侧。

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


通过在两个模型上都指定@JoinColumn,就没有双向关系。你有两个单向关系,这是一个非常令人困惑的映射。您告诉两个模型它们“拥有”IDAIRLINE列。实际上只有一个人应该这样做!“正常”的做法是将@JoinColumn完全从@OneToMany端移除,而是将mappedBy添加到@OneToMany端。

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

它告诉Hibernate“去查看名为‘airline’的bean属性,在我的集合中找到配置。”


Mappedby为自己说话,它告诉hibernate不要映射这个字段。它已经被这个字段[name="field"]映射了。 字段在另一个实体中(类中的变量名而不是数据库中的表)..

如果您不这样做,hibernate将映射这两个关系,因为它没有 同样的关系

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


Mappedby ="在另一个类中创建的同一类的实体的对象"

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

注:—可用于以下注释:— 1 .@OneTone 2 .@OneToMany 3 .@ManyToMany

注意—不能用于以下注释 1 .@ManyToOne

一对一模式:—可在映射的任意一侧执行,但只能在一侧执行。 它将在应用它的类的表上删除外键约束的额外列。

例如:如果我们在雇员对象上应用雇员类中的映射,那么雇员表中的外键将被移除。


你从多对一映射开始,然后你把一对多映射也用于双向方式。 然后在OneToMany端(通常是你的父表/类),你必须提到“mappedBy”(映射是由并且在子表/类中完成的),所以hibernate不会在DB中创建额外的映射表(像TableName = parent_child)。


表关系与实体关系

在关系数据库系统中,一对多表关系如下所示:

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

因此,在管理一对多表关系时,只有一个事实来源。

现在,如果你有一个双向实体关系,映射到我们之前看到的一对多表关系上:

如果您看一下上面的图表,您可以看到有两种方法来管理这种关系。

在Post实体中,你有评论集合:

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

并且,在PostComment中,帖子关联映射如下:

@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);
}

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


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