具有OneToMany和ManyToOne外键类型关系的JPA Hibernate空指针异常

时间:2018-09-07 19:24:16

标签: hibernate jpa orm nullpointerexception spring-data-jpa

我正在尝试为此数据库保留具有@OneToMany和@ManyToOne关系的实体:

Database schema

以下是我创建的实体:
动漫表:

@Entity
@Table(name = "anime")
public class Anime {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "user_id")
   private Integer animeId;

   @Column(name = "anime_name")
   private String animeName;

   @Column(name = "number_of_episodes")
   private Integer numberOfEpisodes;

   @Column(name = "general_rating")
   private Double generalRating;

   @Column(name = "number_of_votes")
   private Integer numberOfVotes;

   @OneToMany(mappedBy = "anime")
   private Set<UserRating> userRatings = new HashSet<>();

   //getters and setters
 }

用户表:

@Entity
@Table(name = "users")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Integer userId;

    @Column(name = "name")
    private String name;

    @Column(name = "password")
    private String password;

    @Column(name = "email")
    private String email;

    @OneToMany(mappedBy = "user")
    private Set<UserRating> userRatings = new HashSet<>();
   //getters and setters
}

以及用户评分表和嵌入式ID:

@Entity
@Table(name = "user_ratings")
public class UserRating {
@Embeddable
public static class UserRatingId implements Serializable{
    @ManyToOne
    @JoinColumn(name = "user_id")
    protected Integer userId;

    @ManyToOne
    @JoinColumn(name = "anime_id")
    protected Integer animeId;

    public UserRatingId() {
    }

    public UserRatingId(Integer userId, Integer animeId) {
        this.userId = userId;
        this.animeId = animeId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserRatingId that = (UserRatingId) o;
        return Objects.equals(userId, that.userId) &&
                Objects.equals(animeId, that.animeId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(userId, animeId);
    }
}

@EmbeddedId
private UserRatingId id;

@ManyToOne
@JoinColumn(name = "user_id")
private User user;

@ManyToOne
@JoinColumn(name = "anime_id")
private Anime anime;

@Column(name = "rating")
private Double rating;
   //getters and setters
}

好的,如此定义所有这些实体和关系,我看到NullPointerException告诉我我搞砸了外键。

Root Cause

java.lang.NullPointerException
org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1749)
org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1658)

但是我不知道如何解决。您能否看一下它,并帮助我找出我搞砸的地方,以便对其进行修复?谢谢。

1 个答案:

答案 0 :(得分:1)

您可以尝试使用派生身份。您将这样映射您的实体:

@Entity
@Table(name = "user_ratings")
public class UserRating {

    @Embeddable
    public static class UserRatingId implements Serializable {
        protected Integer userId; // type matches User's primary key
        protected Integer animeId; // type matches Anime's primary key
        //...
    }

    @EmbeddedId
    private UserRatingId id;

    @MapsId("userId") // maps userId attribute of embedded id
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @MapsId("animeId") // maps animeId attribute of embedded id
    @ManyToOne
    @JoinColumn(name = "anime_id")
    private Anime anime;

    //...
}

JPA 2.2 spec的第2.4.1节中讨论了派生的身份(带有示例)。