简体   繁体   English

Spring JPA-数据完整性关系

[英]Spring JPA - Data integrity relationships

I'm new to Java and even more newer to Spring (Boot and JPA) but I was curious, I'm trying to debug an issue that says, "No identifier specified for entity". 我是Java的新手,还是Spring的新手(Boot和JPA),但我很好奇,我正在尝试调试一个问题,即“未为实体指定标识符”。

For illustartion purposes, I've created the following tables from this diagram: 出于说明目的,我从该图中创建了以下表格:

在此处输入图片说明

Originally, there was a M:N relationship between the user and vehicle table, so I created an associative entity (UserVehicleAsso) to split the two up. 最初,用户表和车辆表之间存在M:N关系,因此我创建了一个关联实体(UserVehicleAsso)来将两者分开。 I was following this guide on M:N mapping in Java, http://viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/ 我正在遵循有关Java中M:N映射的指南, http://viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/

For the most part, it was pretty straight forward but my question is, within the associative entity (UserVehicleAsso), do I have to use the @Id annotation for each of the foreign keys? 在大多数情况下,这很简单,但是我的问题是,在关联实体(UserVehicleAsso)中,是否必须对每个外键使用@Id注释? I assume that I didn't need to because those were automatically generated from each of the respective tables. 我以为不需要,因为这些是从各个表中自动生成的。

Let me know your thoughts or comments, thanks. 让我知道您的想法或意见,谢谢。

Also, below is the code that I used to generate these models: 另外,以下是我用来生成这些模型的代码:

For the User table/class: 对于用户表/类:

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

For the Vehicle table/class: 对于车辆表/类:

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


}

And then finally, my associtive table/class: 最后,我的关联表/类:

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


}

In my opinion, it's not necessary to have an Entity class for the middle table in your case. 我认为,在您的情况下,中间表不必具有Entity类。 The table will be generated automatically if configured correctly. 如果配置正确,该表将自动生成。 In this table, there would not be column ID , only two columns with userID and vehicleID data. 在此表中,将没有列ID ,只有两列包含userID IDvehicleID数据。

Now, if your middle table has more than what are needed to establish the M:N relationship, then your middle Entity class is needed, and the ID of it, too. 现在,如果您的中间表具有超出建立M:N关系所需的内容,那么就需要中间Entity类以及它的ID For example, if this class is intended to store the time stamp every time a relationship is established, you have to: 例如,如果此类旨在在每次建立关系时存储时间戳,则您必须:

  1. Create this Entity class, 创建此Entity类,
  2. Give it an ID field with proper generation strategy, 给它一个ID字段,并使用适当的生成策略
  3. Map the time stamp with a field with adequate type, annotation/XML mapping and so on. 使用具有适当类型,注释/ XML映射等的字段来映射时间戳。

This part of JPA/Hibernate have confused me a lot and I used to get into them. JPA / Hibernate的这一部分使我很困惑,我以前经常接触到它们。 If my memory serves me well this is the proper/perfect way how things should work. 如果我的记忆力对我有益,那么这就是正确/完美的工作方式。

You can specify a composite primary key class that is mapped to multiple fields or properties of the entity. 您可以指定一个组合主键类,该主键类映射到实体的多个字段或属性。

Here are sample codes: 以下是示例代码:

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

associtive table/class: 关联表/类:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM