Good idea, thanks revilo! I modified the code based on your suggestion and got around the validation problem. Unfortunately, I have now run into an additional problem. When I attempt to add a Room (number=199) to a Floor (id=1) and persist them to the database, I get this exception:
Quote:
org.hibernate.exception.GenericJDBCException: could not insert: [hotel.Room]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2263)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2656)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:52)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at hotel.HibernateTest.main(HibernateTest.java:34)
Caused by: java.sql.SQLException: Parameter index out of bounds. 3 is not between valid values of 1 and 2
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
at com.mysql.jdbc.ServerPreparedStatement.getBinding(ServerPreparedStatement.java:768)
at com.mysql.jdbc.ServerPreparedStatement.setInt(ServerPreparedStatement.java:1778)
at org.hibernate.type.IntegerType.set(IntegerType.java:41)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:136)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:116)
at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:284)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2004)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2239)
... 9 more
It looks like Hibernate is generating an extra parameter for an insert statement. But the statement itself looks ok:
Quote:
2007-03-06 14:46:09,140 DEBUG [org.hibernate.SQL] - <insert into rooms (floor_id, number) values (?, ?)>
Hibernate: insert into rooms (floor_id, number) values (?, ?)
2007-03-06 14:46:09,187 INFO [org.hibernate.type.IntegerType] - <could not bind value '199' to parameter: 3; Parameter index out of bounds. 3 is not between valid values of 1 and 2>
The correct parameters should be (1, 199). I don't see the actual parameters Hibernate is trying to bind anywhere in the output, but I'm guessing they're (1, 199, 199) and Hibernate thinks there's a second column for the room number. But I don't know why. Any more thoughts?
The latest Floor class has a new method, addRoom():
Code:
@Entity
@Table(name="floors")
public class Floor {
private int id;
private List<Room> rooms;
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@OneToMany(cascade=CascadeType.ALL, mappedBy="floor")
public List<Room> getRooms() {
return rooms;
}
public void setRooms(List<Room> rooms) {
this.rooms = rooms;
}
public void addRoom(Room room) {
room.setFloor(this);
rooms.add(room);
}
}
While Room and RoomKey have been more extensively updated:
Code:
@Entity
@IdClass(hotel.RoomKey.class)
@Table (name="rooms")
public class Room {
private Floor floor;
private RoomKey id;
public Room() {
id = new RoomKey();
}
@Id
public RoomKey getId () {
return id;
}
public void setId(RoomKey id) {
this.id = id;
}
public int getFloorId() {
return id.getFloorId();
}
public void setFloorId(int floorId) {
id.setFloorId(floorId);
}
public int getNumber() {
return id.getNumber();
}
public void setNumber(int number) {
id.setNumber(number);
}
@ManyToOne
@JoinColumn(name="floor_id", insertable=false, updatable=false)
public Floor getFloor() {
return floor;
}
public void setFloor(Floor floor) {
this.floor = floor;
}
}
Code:
@Embeddable
public class RoomKey implements Serializable {
private static final long serialVersionUID = 4226995603575410303L;
private int floorId;
private int number;
@Column(name="floor_id", insertable=false, updatable=false)
public int getFloorId() {
return floorId;
}
public void setFloorId(int cardSetId) {
this.floorId = cardSetId;
}
public int getNumber() {
return number;
}
public void setNumber(int position) {
this.number = position;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
else if (o instanceof RoomKey) {
return floorId == ((RoomKey)o).getFloorId() &&
number == ((RoomKey)o).getNumber();
}
return false;
}
@Override
public int hashCode() {
return floorId ^ number;
}
}
I've been playing with @EmbeddedId vs @IdClass, and so far I haven't gotten @EmbeddedId to work, although apparently I do need to put @Embeddable in my key. I feel like I haven't quite got matching annotations from one class to the next, so I'm going to try playing around with that next. Also I think I'll try to let Hibernate generate my table and see what it comes up with.