【问题标题】:org.hibernate.PropertyAccessException: with many to many relationorg.hibernate.PropertyAccessException:具有多对多关系
【发布时间】:2013-02-15 18:37:01
【问题描述】:

我在为多对多关系(用户和消息表)建立新表(用户消息)时遇到了问题。当我尝试访问映射表中的一行时,出现异常:org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.package.model.User.userid

UserMessage 实体是进一步向关系表添加属性所必需的。

通过以下方式访问数据:

    Session session = (Session) entityManager.getDelegate();
    String hql = "FROM Message M, UserMessage UM WHERE M.messageid = UM.pk.message and UM.pk.user = :id";
    Query query = session.createQuery(hql);
    query.setParameter("id", id);
    query.list();

我的课:

User.java

@Entity
@Table(name = "USER")
public class User {
    @Id @GeneratedValue(generator="system-uuid")
    @GenericGenerator(name="system-uuid", strategy = "uuid")
    @Column(nullable = false)
    private Long userid;

    @Column(unique = true, nullable = false)
    private String username;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.user", cascade = {CascadeType.PERSIST})
    private Set<UserMessage> inbox = new HashSet<UserMessage>();

    public User() {
    }

    public Long getUserid() {
        return userid;
    }

    public void setUserid(Long id) {
        this.userid = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Set<UserMessage> getInbox() {
        return inbox;
    }

    public void setInbox(Set<UserMessage> inbox) {
        this.inbox = inbox;
    }

    public void addMessageToUser(Message message){
        UserMessage userMessage = new UserMessage();
        userMessage.setUser(this);
        userMessage.setMessage(message);
        inbox.add(userMessage);
    }
}

Message.java

@Entity
@Table(name = "MESSAGE")
public class Message {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long messageid;
    private String subject;
    private String body;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.message",cascade = {CascadeType.PERSIST})
    private Set<UserMessage> toUser = new HashSet<UserMessage>();

    public Set<UserMessage> getToUser() {
        return toUser;
    }

    public void setToUser(Set<UserMessage> toUser) {
        this.toUser = toUser;
    }

    public void addUserToMessage(User user){
        UserMessage userMessage = new UserMessage();
        userMessage.setUser(user);
        userMessage.setMessage(this);
        toUser.add(userMessage);
    }

    public Message() {
    }

    public Long getMessageid() {
        return messageid;
    }

    public void setMessageid(Long id) {
        this.messageid = id;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}

UserMessage.java

@Entity
@Table(name = "USER_MESSAGE")
@AssociationOverrides({
        @AssociationOverride(name = "pk.user", joinColumns = @JoinColumn(name = "userid")),
        @AssociationOverride(name = "pk.message", joinColumns = @JoinColumn(name = "messageid"))
})
public class UserMessage{

    @EmbeddedId
    private UserMessagePK pk = new UserMessagePK();


    public UserMessagePK getPk(){
        return pk;
    }

    public void setPk(UserMessagePK pk){
        this.pk = pk;
    }

    public UserMessage(){
    }

    @Transient
    public User getUser(){
        return this.pk.getUser();
    }

    @Transient
    public Message getMessage(){
        return this.pk.getMessage();
    }

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

    public void setMessage(Message message){
        this.pk.setMessage(message);
    }
}

UserMessagePK.java

@Embeddable
public class UserMessagePK implements Serializable {

    private static final long serialVersionUID = 1L;

    @ManyToOne
    private User user;

    @ManyToOne(cascade = CascadeType.REFRESH)
    private Message message;

    public User getUser() {
        return user;
    }

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


    public Message getMessage() {
        return message;
    }

    public void setMessage(Message message) {
        this.message = message;
    }

    public UserMessagePK(User user, Message message){
        this.user = user;
        this.message = message;
    }

    public UserMessagePK(){
    }
}

怎么了?

【问题讨论】:

  • 为什么要使用@EmbeddedId?
  • @forhas 因为 UserMessagePK 是复合主键,不是吗?

标签: hibernate jpa many-to-many


【解决方案1】:

问题出在查询中。

select distinct M from Message M join M.toUser t where t.pk.user = :user 完美运行。

【讨论】:

    【解决方案2】:

    我会建议一种不同的方法。 在 User 类中,不要持有一组 UserMessage,而是这样写:

    @Entity
    @Table(name = "Users")
    public class User implements Serializable {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "User_Id")
    private Long userid;
    
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinTable(name = "USER_MESSAGE", joinColumns = @JoinColumn(name = "User_Id"), inverseJoinColumns = @JoinColumn(name = "Message_Id"))
    protected Set<Message> userMessages = new HashSet<>(0);
    
    public void addUserMessage(Message toAdd) {
    if (null != toAdd) {
        this.userProviders.add(toAdd);
    }
    }
    
    public void getUserMessages() {
    return this.userMessages;
    }
    
    public void setUserMessages(Set<Message> userMessages) {
    this.userMessages.clear();
    this.userMessages.addAll(userMessages);
    }
    
    // add getter and setter to id
    

    ...

    在 Message 类中你应该有:

    @Entity
    @Table(name = "User_Messages")
    public class Message implements Serializable {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Message_Id")
    protected long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinTable(name = "Users_Messages", joinColumns = @JoinColumn(name = "Message_Id", insertable = false, updatable = false), inverseJoinColumns = @JoinColumn(name = "User_Id"))
    protected User user;
    
    // add getters and setters
    ...
    

    您也可以摆脱 UserMessagePK 类和 UserMessage (为什么需要这些?)。 现在,当您生成表时(您可以使用 hbm2ddl tool),您应该有一个用于 UserMessage 关系的连接表。

    现在您可以运行查询了。

    【讨论】:

    • 感谢您的回复,但我忘了说创建映射类的目的是映射表中的其他元素。据我所知,没有单独的实体是不可能的。
    • 我同意。我现在得走了,不过明天我会努力找时间再看看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多