2013-02-15 4 views
0

Я столкнулся с проблемой при создании новой таблицы (UserMessage) для отношения многих и многих (таблицы пользователей и сообщений). Когда я пытаюсь получить доступ к строке из таблицы сопоставлений, я получаю исключение: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.package.model.User.useridorg.hibernate.PropertyAccessException: со многими для многих отношений

Объект 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(){ 
    } 
} 

Что не так?

+0

Зачем вам использовать @EmbeddedId? – forhas

+0

@forhas Поскольку UserMessagePK является составным первичным ключом, не так ли? – rbobin

ответ

1

Проблема была в запросе.

select distinct M from Message M join M.toUser t where t.pk.user = :user работает отлично.

0

Я бы предложил другой подход. В классе пользователя, вместо того чтобы держать набор 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 

...

В классе сообщений Вы должны иметь:

@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), у вас должна быть таблица соединений для отношения пользователя < -> Сообщение.

Теперь вы можете запускать свои запросы.

+0

Спасибо за ваш ответ, но я забыл упомянуть, что целью создания классов сопоставления являются другие элементы в таблице сопоставления. Насколько я знаю, это невозможно без отдельного объекта. – rbobin

+1

Согласен. Я должен уйти сейчас, но я постараюсь найти время, чтобы снова посмотреть завтра. – forhas

Смежные вопросы