16

我有一个名为“EventCheckin”的模型,它有一个多对一映射到一个“事件”和一个“用户”。“EventCheckin”表的PrimaryKey是用户的id和事件的id。我试图在我的 EventCheckin 模型中使用“EmbeddedId”来表示这一点,但是当我尝试保存 EventCheckin 时,它会尝试将 user_id 和 event_id 值两次放入表中,这显然失败了:

Caused by: org.h2.jdbc.JdbcSQLException: Duplicate column name "USER_ID"; SQL statement:
insert into eventCheckin (event_id, user_id, latitude, longitude, user_id, event
_id) values (?,?,?,?,?,?) [42121-158]

EventCheckin 类:

@Entity
@Table(name="eventCheckin")
public class EventCheckin extends Model
{
    @EmbeddedId public CheckinId id;

    @MapsId("userId")
    @JoinColumn(name="user_id")
    @ManyToOne public User user;

    @MapsId("eventId")
    @JoinColumn(name="event_id")
    @ManyToOne public Event event;

    .....
}

CheckinId EmbeddedId 类::

@Embeddable 
public class CheckinId implements Serializable
{
    public Long eventId;  
    public String userId;
    .....
}

我的 EventCheckin 数据库表定义如下:

create table eventCheckin (
    user_id                   varchar(255) not null,
    event_id                  bigint not null,
    latitude                  float,
    longitude                 float,
    constraint pk_eventCheckIn primary key (user_id,event_id),
    foreign key (user_id) references user (email),
    foreign key (event_id) references event (id)
);
4

2 回答 2

2

看起来您尝试通过@MapsId 和@EmbeddedId 做同样的事情。一个(工作)选项是使用 IdClass (等于、哈希码、额外属性等被删除):

    @Entity
    public class User {
        @Id public String id;
    }

    @Entity
    public class Event {
        @Id public long id;
    }

    public class CheckinId implements Serializable {
        public Long event;
        public String user;
    }

    @Entity
    @IdClass(CheckinId.class)
    @Table(name="eventCheckin")
    public class EventCheckin {

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

        @Id
        @JoinColumn(name="event_id")
        @ManyToOne public Event event;
    }
于 2012-03-26T18:35:57.153 回答
2

发生此错误是因为列user_idevent_id由复合键使用,同时它们被@ManyToOne映射使用。解决方案是在注释中添加insertable = false, updatable = false属性@Joincolumn。这是此解决方案的工作代码:

EventChekin.java:

@Entity
@Table(name="eventCheckin")
public class EventCheckin extends Model {

    public EventCheckin() {
        id = new CheckinId();
    }

    @EmbeddedId 
    public CheckinId id;

    @ManyToOne
    @MapsId("userId")
    @JoinColumn(name="user_id", insertable = false, updatable = false)
    private User user;

    @ManyToOne
    @MapsId("eventId")
    @JoinColumn(name="event_id", insertable = false, updatable = false)
    private Event event;

    public void setUser(User aUser) {
        user = aUser;
        id.userId = aUser.getId();
    }

    public void setEvent(Event aEvent) {
        event = aEvent;
        id.eventId = aEvent.getId();
    }
}

签入.java

@Embeddable 
public class CheckinId implements Serializable {

    public Long eventId;
    public String userId;

    @Override
    public int hashCode() {
        return eventId.intValue() + userId.length();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) 
            return true;
        CheckinId c = (CheckinId)obj;
        if(c==null)
        return false;
        if (c.eventId.equals(eventId) && c.userId.equals(userId)) {
            return true;
        }
        return false;
    }
}
于 2014-11-30T22:14:59.300 回答