В Postgres 9.4 или новее это, вероятно, простейшее и быстрое :
SELECT c.*
FROM comments c
JOIN unnest('{1,3,2,4}'::int[]) WITH ORDINALITY t(id, ord) USING (id)
ORDER BY t.ord;
WITH ORDINALITY
что @a_horse уже упоминается . Подробное объяснение:
После долгих экспериментов и разочарований я в конце концов решил, что не могу делать именно то, что хочу.
В конечном счете, я пошел дальше и дал дочернему объекту свой собственный синтетический ключ и позволил Hibernate управлять им. Это не идеально, так как ключ почти такой же большой, как и остальные данные, но он работает.
Вы должны включить ссылку ParentObject
только в ChildObject.Pk
, а не сопоставлять parent и parentId по отдельности:
(методы получения, установки, атрибуты Hibernate не связаны с проблемой и ключевые слова доступа к элементам опущены)
class ChildObject {
@Embeddable
static class Pk {
@ManyToOne...
@JoinColumn(name="parentId")
ParentObject parent;
@Column...
String name...
...
}
@EmbeddedId
Pk id;
}
В ParentObject
вы просто помещаете @OneToMany(mappedBy="id.parent")
, и это работает.
Книга Маннинга Сохранение Java с Hibernate содержит пример, описывающий, как это сделать, в Разделе 7.2. К счастью, даже если вы не являетесь владельцем книги, вы можете увидеть пример этого исходного кода, загрузив JPA-версию примера проекта Caveat Emptor (прямая ссылка здесь ) и изучение классов Category
и CategoryizedItem
в пакете uction.model
.
Я также резюмирую основные аннотации ниже. Дай мне знать, если это все еще не разрешено.
ParentObject:
@Entity
public class ParentObject {
@Id @GeneratedValue
@Column(name = "parentId", nullable=false, updatable=false)
private Long id;
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@IndexColumn(name = "pos", base=0)
private List<ChildObject> attrs;
public Long getId () { return id; }
public List<ChildObject> getAttrs () { return attrs; }
}
ChildObject:
@Entity
public class ChildObject {
@Embeddable
public static class Pk implements Serializable {
@Column(name = "parentId", nullable=false, updatable=false)
private Long objectId;
@Column(nullable=false, updatable=false)
private String name;
@Column(nullable=false, updatable=false)
private int pos;
...
}
@EmbeddedId
private Pk id;
@ManyToOne
@JoinColumn(name="parentId", insertable = false, updatable = false)
@org.hibernate.annotations.ForeignKey(name = "FK_CHILD_OBJECT_PARENTID")
private ParentObject parent;
public Pk getId () { return id; }
public ParentObject getParent () { return parent; }
}
Во-первых, в ParentObject
"исправьте" атрибут mappedBy
, который должен быть установлен в "parent"
. Также (но это, возможно, опечатка) добавьте аннотацию @Id
:
@Entity
public class ParentObject {
@Id
@GeneratedValue
private String id;
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@IndexColumn(name = "pos", base=0)
private List<ObjectChild> attrs;
// getters/setters
}
Затем в ObjectChild
добавьте атрибут name
к objectId
в составном ключе:
@Entity
public class ObjectChild {
@Embeddable
public static class Pk implements Serializable {
@Column(name = "parentId", nullable = false, updatable = false)
private String objectId;
@Column(nullable = false, updatable = false)
private String name;
@Column(nullable = false, updatable = false)
private int pos;
}
@EmbeddedId
private Pk pk;
@ManyToOne
@JoinColumn(name = "parentId", insertable = false, updatable = false)
private ParentObject parent;
// getters/setters
}
И также добавьте insertable = false, updatable = false
к @JoinColumn
, потому что мы повторяем колонку parentId
в отображении этой сущности.
С этими изменениями персистенция и чтение сущностей работает нормально (проверено на Derby).