Я использую Hibernate 3.5.2-FINAL с аннотациями, чтобы указать мои сопоставления персистентности. Я борюсь с моделированием отношений между Приложением и набором платформ. Каждое приложение доступно для набора платформ.
Из всех проверок и поиска, которые я сделал, я думаю, что мне нужно, чтобы класс перечисления платформы сохранялся как Entity, и иметь таблицу соединений для представления отношений "многие ко многим". Я хочу, чтобы отношения были однонаправленными на уровне объекта, то есть я хотел бы получить список платформ для данного приложения, но мне не нужно искать список приложений для данной платформы.
Вот мои упрощенные классы моделей:
@Entity
@Table(name = "TBL_PLATFORM")
public enum Platform {
Windows,
Mac,
Linux,
Other;
@Id
@GeneratedValue
@Column(name = "ID")
private Long id = null;
@Column(name = "NAME")
private String name;
private DevicePlatform() {
this.name = toString();
}
// Setters and getters for id and name...
}
@Entity
@Table(name = "TBL_APP")
public class Application extends AbstractEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "NAME")
protected String _name;
@ManyToMany(cascade = javax.persistence.CascadeType.ALL)
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
@JoinTable(name = "TBL_APP_PLATFORM",
joinColumns = @JoinColumn(name = "APP_ID"),
inverseJoinColumns = @JoinColumn(name = "PLATFORM_ID"))
@ElementCollection(targetClass=Platform.class)
protected Set<Platform> _platforms;
// Setters and getters...
}
Когда я запускаю инструмент Hibernate hbm2ddl, я вижу следующее (я использую MySQL):
create table TBL_APP_PLATFORM (
APP_ID bigint not null,
PLATFORM_ID bigint not null,
primary key (APP_ID, PLATFORM_ID)
);
Соответствующие внешние ключи также создаются из этой таблицы в таблицу приложений и таблицу платформы. Пока все хорошо.
Одна проблема, с которой я сталкиваюсь, - это когда я пытаюсь сохранить объект приложения:
Application newApp = new Application();
newApp.setName("The Test Application");
Set<DevicePlatform> platforms = EnumSet.of(Platform.Windows, Platform.Linux);
newApp.setPlatforms(platforms);
applicationDao.addApplication(newApp);
Мне бы хотелось, чтобы соответствующие строки в таблице Platform создавались, т.е. создавали строку для Windows и Linux, если они еще не существуют. Затем должна быть создана строка для нового приложения, а затем сопоставление между новым приложением и двумя платформами в таблице соединений.
Одна проблема, с которой я столкнулся, - это следующее исключение для выполнения:
2010-06-30 13:18:09,382 6613126-0 ERROR FlushingEventListener Could not synchronize database state with session org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.example.model.Platform
Как бы то ни было, набор инструментов не сохраняется, когда я пытаюсь сохранить приложение. Каскадные аннотации должны заботиться об этом, но я не знаю, что случилось.
Итак, мои вопросы:
- Есть ли лучший способ моделирования того, что я хочу сделать, например. использует Enum подходящий?
- Если моя модель в порядке, как я правильно сохраняю все объекты?
Я боролся с этим в течение нескольких часов, и я попытался воссоздать весь код выше, но он может быть не полным и/или точным. Я надеюсь, что кто-то укажет на что-то очевидное!