Spring JPA - 数据完整性关系

时间:2016-11-03 22:03:51

标签: java spring-boot spring-data-jpa

我是Java的新手,对Spring(Boot和JPA)更新,但我很好奇,我试图调试一个问题,"没有为实体指定标识符&# 34 ;.

出于Illustartion目的,我已从此图表中创建了以下表格:

enter image description here

最初,用户和车辆表之间存在M:N关系,因此我创建了一个关联实体(UserVehicleAsso)来将两者分开。我在Java,http://viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/

上遵循M:N映射的本指南

在大多数情况下,它非常简单,但我的问题是,在关联实体(UserVehicleAsso)中,我是否必须为每个外键使用@Id注释?我认为我不需要,因为这些是从每个表中自动生成的。

让我知道你的想法或意见,谢谢。

另外,下面是我用来生成这些模型的代码:

对于User表/类:

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int userId;

private String fName;
private String lName;

@ManyToMany(cascade = {CascadeType.ALL})
@JoinTable(name="userVehicleAsso", 
            joinColumns={@JoinColumn(name="userID")}, 
            inverseJoinColumns={@JoinColumn(name="vehicleID")})
private Set<Vehicle> vehicles = new HashSet<Vehicle>();


//constructor
protected User() {}


public int getUserId() {
    return userId;
}
public void setUserId(int userId) {
    this.userId = userId;
}
public String getFName() {
    return fName;
}
public void setFName(String fName) {
    this.fName = fName;
}
public String getLName() {
    return lName;
}
public void setLName(String lName) {
    this.lName = lName;
}



public Set<Vehicle> getVehicles() {
    return vehicles;
}

public void setVehicles(Set<Vehicle> vehicles) {
    this.vehicles = vehicles;
}

@Override 
public String toString() {
    return getFName() + "," + getLName();
}}

对于Vehicle表/类:

@Entity
public class Vehicle {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int vehicleId;

private String brand;
private String model;
//foreign key mappings
//mapping with associative
@ManyToMany(mappedBy="vehicles")
private Set<User> users = new HashSet<User>();


//constructors
protected Vehicle() {}

public Vehicle(int id) {
    this.vehicleId = id;
}

public Vehicle (String brand, String model) {
    this.brand = brand;
    this.model = model;
}

/*  public Vehicle() {

}*/


public int getVehicleId() {
    return vehicleId;
}
public Set<User> getUsers() {
    return users;
}

public void setUsers(Set<User> users) {
    this.users = users;
}


public void setVehicleId(int vehicleId) {
    this.vehicleId = vehicleId;
}
public String getBrand() {
    return brand;
}

public void setBrand(String brand) {
    this.brand = brand;
}

public String getModel() {
    return model;
}

public void setModel(String model) {
    this.model = model;
}
@Override
public String toString() {
    // + setBodyType() + "," +
    return getBrand() + "," + getModel();
}


}

最后,我的关联表/类:

@Entity
public class UserVehicleAsso{

private int userID;
private int vehicleID;

public int getUserID() {
    return userID;
}
public void setUserID(int userID) {
    this.userID = userID;
}
public int getVehicleID() {
    return vehicleID;
}
public void setVehicleID(int vehicleID) {
    this.vehicleID = vehicleID;
}


}

2 个答案:

答案 0 :(得分:1)

在我看来,在你的情况下没有必要为中间表创建一个Entity类。如果配置正确,将自动生成该表。在此表中,不会有列ID,只有两列包含userIDvehicleID数据。

现在,如果你的中间表有超过建立M:N关系所需的中间表,那么你需要你的中间实体类,以及它的ID。例如,如果此类用于在每次建立关系时存储时间戳,则必须:

  1. 创建此实体类
  2. 使用适当的生成策略为其提供ID字段,
  3. 使用具有足够类型,注释/ XML映射等的字段映射时间戳。
  4. JPA / Hibernate的这一部分让我很困惑,而且我过去常常陷入困境。如果我的记忆对我有好处,这就是事情应该如何运作的正确/完美方式。

答案 1 :(得分:0)

您可以指定映射到实体的多个字段或属性的复合主键类。

以下是示例代码:

public class ActivityRegPK implements Serializable {
    private int activityId;

    private int memberId;

    public int getActivityId() {
        return activityId;
    }

    public void setActivityId(int activityId) {
        this.activityId = activityId;
    }

    public int getMemberId() {
        return memberId;
    }

    public void setMemberId(int memberId) {
        this.memberId = memberId;
    }
}

关联表/类:

@IdClass(ActivityRegPK.class)
@Entity
@Table(name="activity_reg")
@NamedQuery(name="ActivityReg.findAll", query="SELECT a FROM ActivityReg a")
public class ActivityReg implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="activity_id")
    private int activityId;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="ins_date")
    private Date insDate;

    @Id
    @Column(name="member_id")
    private int memberId;
}

Activity.class

@Entity
@NamedQuery(name="Activity.findAll", query="SELECT a FROM Activity a")
public class Activity implements Serializable {
    // some attributes
}