JPA系统异常错误访问字段

时间:2018-07-01 00:38:55

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

我正在尝试使用spring + JPA在实体之间实现单向多对多关系。

尝试几次更改休眠版本后,我不知道是什么原因

由以下原因引起:org.springframework.orm.jpa.JpaSystemException:通过持久性属性[com.uca.refactor2]的反射访问字段[private java.lang.Integer com.uca.refactor2.model.Achievement.id]时出错。 model.Achievement#id]:1;嵌套的异常是org.hibernate.property.access.spi.PropertyAccessException:通过对持久属性[com.uca.refactor2.model的反射]访问字段[private java.lang.Integer com.uca.refactor2.model.Achievement.id]时出错.Achievement#id]:1

User.java

@Entity
@Table(name="USER")
public class User implements Serializable {

private static final long serialVersionUID = 4402583037980335445L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String firstName;
private String lastName;
@Column(unique = true)
private String username;
private String password;
@Enumerated(EnumType.STRING) 
private UserType  userType;

@OneToMany(cascade=CascadeType.ALL, mappedBy="joinedUserAchievementId.user")
private List<JoinedUserAchievement> joinedUserAchievementList = new ArrayList<JoinedUserAchievement>();

public User() {}

public User(Integer id) {
    this.id = id;
}
public User(String username, String firstName, String lastName,
        String password, UserType userType) {
    this.username = username;
    this.firstName = firstName;
    this.lastName = lastName;
    this.password = password;
    this.userType = userType;
}


public List<JoinedUserAchievement> getAllAchievement() {
        return joinedUserAchievementList;
}
public void addAchievement(Achievement achievement) {
    // Notice a JoinedUserAchievement object
    Date dateOfAcquisition = new Date();
    JoinedUserAchievement joinedUserAchievement = new JoinedUserAchievement(new JoinedUserAchievement.JoinedUserAchievementId(this, achievement),dateOfAcquisition );
    joinedUserAchievement.setAchievementId(achievement.getId());
    joinedUserAchievementList.add(joinedUserAchievement);
}
//set and gets

JoinedUserAchievement.java

@Entity
@Table(name="USER_ACHIEVEMENT")
public class JoinedUserAchievement {

public JoinedUserAchievement() {}

public JoinedUserAchievement(JoinedUserAchievementId joinedUserAchievementId, Date dateOfAcquisition) {
    this.joinedUserAchievementId = joinedUserAchievementId;
    this.dateOfAcquisition = dateOfAcquisition;
}

@ManyToOne(targetEntity = Achievement.class)
@JoinColumn(name="id", insertable=false, updatable=false)
private Integer achievementId;

private Date dateOfAcquisition;

public String getDate()  {
    DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
    Date date = dateOfAcquisition;
    return dateFormat.format(date); 
}

public Integer getAchievementId() {
    return achievementId;
}

public void setAchievementId(Integer achievementId) {
    this.achievementId = achievementId;
}

@EmbeddedId
private JoinedUserAchievementId joinedUserAchievementId;


// required because JoinedUserAchievments contains composite id
@Embeddable
public static class JoinedUserAchievementId implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -9180674903145773104L;


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

    @ManyToOne
    @JoinColumn(name="ACHIEVEMENT_ID")
    private Achievement achievement;

    // required no arg constructor
    public JoinedUserAchievementId() {}

    public JoinedUserAchievementId(User user, Achievement achievement) {
        this.user = user;
        this.achievement = achievement;
    }

    public JoinedUserAchievementId(Integer userId, Integer achievementId) {
        this(new User(userId), new Achievement(achievementId));
    }

    public User getUser() {
        return user;
    }

    public Achievement getAchievement() {
        return achievement;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public void setAchievement(Achievement achievement) {
        this.achievement = achievement;
    }
    @Override
    public boolean equals(Object instance) {
        if (instance == null)
            return false;

        if (!(instance instanceof JoinedUserAchievementId))
            return false;

        final JoinedUserAchievementId other = (JoinedUserAchievementId) instance;
        if (!(user.getId().equals(other.getUser().getId())))
            return false;

        if (!(achievement.getId().equals(other.getAchievement().getId())))
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 47 * hash + (this.user != null ? this.user.hashCode() : 0);
        hash = 47 * hash + (this.achievement != null ? this.achievement.hashCode() : 0);
        return hash;
    }
}
}

Achievement.java

@Entity
@Table(name="ACHIEVEMENT")
public class Achievement implements Serializable{

private static final long serialVersionUID = 7747630789725422177L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

private Integer id;
private String name;
private Integer points;


public Achievement() {

}
public Achievement(String name, Integer points) {
    this.name = name;
    this.points = points;
}

public Achievement(Integer id) {
    this.id = id;
}
//set and gets

我也试图使这种关系成为双向,但是这种关系不起作用,所以我可能会遗漏一些东西

在此之前,我还没有Achivement对象而不是joinUserAchievement上的achivementId,它可以工作,但是我认为这不是我所需要的,我不需要总是获得每个成就对象,只需id就可以了。

1 个答案:

答案 0 :(得分:1)

来自docs

  

不支持在嵌入式id类中定义的关系映射

您应仅将id放在JoinedUserAchievementId中,并将UserAchievement关联直接放在JoinedUserAchievement中,如下所示:

public class JoinedUserAchievementId {

    private Long userId;
    private Long achievementId;
    ...
}

public class JoinedUserAchievement {

    @EmbeddedId
    private JoinedUserAchievementId joinedUserAchievementId;

    @ManyToOne
    @MapsId("userId")
    @JoinColumn(name = "USER_ID")
    private User user;

    @ManyToOne(optional = false, fetch = LAZY)
    @MapsId("achievementId")
    @JoinColumn(name = "ACHIEVEMENT_ID")
    private Achievement achievement;

    //if you absolutely need to map the achievement_id column here as well
    //note that it will already be mapped to joinedUserAchievementId.achievementId
    @Column(name = "ACHIEVEMENT_ID", insertable=false, updatable=false)
    private Long achievementId;
    ...
}

请记住将User.joinedUserAchievementList映射更新为mappedBy="user"