4

I have two tables, a user table and a user_avatar table. For each user, there are 3 records in the user_avatar table, for 3 sizes of avatars (large, medium, small).

The user_avatar table has a userId column which refers to the User.id field to specify to which user an avatar belongs to.

Here's my UserAvatar class:

@Entity @Table(name = "user_avatar")

public class UserAvatar
{
    @Id @GeneratedValue
    private long id;

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

    @Enumerated(EnumType.STRING)
    private AvatarSize size;

    private String file;
    private String s3Key;

    @Override
    public String toString()
    {
        return size + " " + file;
    }
}

And here's how I'm referring to it in the `user

@Entity
public class User
{
    @Id @GeneratedValue
    public Long id;

    @OneToMany
    @JoinColumn(name = "id")
    @OrderColumn(name = "id")
    public UserAvatar[] avatar; //declared array as there'd be at least 3 records
}

When I run this code, I get the error:

Repeated column in mapping for collection: com.xxx.User.avatar column: id

What am I doing wrong?

Ali
  • 261,656
  • 265
  • 575
  • 769

2 Answers2

4

What you are doing here is a bidrectional many-to-one, where you want to populate objects on both sides of the relationship.

Hibernate will complain if you have a JoinColumn on both sides, so just put it on the "owning" side and add mappedBy to the other side.

See this example:

public class UserAvatar {
    ...

    @ManyToOne
    @JoinColumn(name="userId") // userId is the name of your database FK column
    private User user;

    ...
}

public class User {
    ...

    @OneToMany(mappedBy="user")
    public List<UserAvatar> avatars;

    ...
}

As for the particular error you were getting, I believe that was caused by JoinColumn("id") in User conflicting with the primary key column id.

Also see this SO answer.

Community
  • 1
  • 1
theblang
  • 10,215
  • 9
  • 69
  • 120
1

Hibernate will maintain an association's order when you use a List or an array. To do that, it needs an integer column in the many-side table to store the record's position in the List/array. You can either:

  1. Change your field to use a Set, for which Hibernate will not attempt to maintain ordering.
  2. Add an integer type column to your database to store the record order, and name that in the @OrderColumn annotation.
Peter Bratton
  • 6,302
  • 6
  • 39
  • 61
  • Looks like it to me, at least according to your description. – Peter Bratton Feb 26 '14 at 17:10
  • I changed `UserAvatar[]` to `Set`, and now I get this: `org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.xxx.User.avatar references an unknown entity: java.util.Set` – Ali Feb 26 '14 at 17:12
  • You need to map both sides. `@ManyToOne` goes on the One side, `@OneToMany` goes on the collection side. – Peter Bratton Feb 26 '14 at 17:17
  • I would highly recommend working through a tutorial before going any further. – Peter Bratton Feb 26 '14 at 17:18
  • I'm now getting `Repeated column in mapping for collection: com.xxx.User.avatar column: id` after my last edit. Totaly stumped on what I'm doing wrong – Ali Feb 26 '14 at 17:48
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/48507/discussion-between-peter-bratton-and-click-upvote) – Peter Bratton Feb 26 '14 at 18:02