Я объяснил свой сценарий с помощью простых таблиц Parent Child.
Мой составной первичный ключ также является составным внешним ключом, ссылающимся на родительскую таблицу.
create table parent(
code varchar(10) not null,
id int not null,
parentcol varchar(10),
primary key(code,id)
);
create table child(
code varchar(10) not null,
id int not null,
childcol varchar(10) not null,
primary key(code, id),
foreign key(code, id) references parent(code,id)
);
Созданные объекты (с помощью плагина Eclipse JPA)
@Entity
@Table(name="parent")
@NamedQuery(name="Parent.findAll", query="SELECT p FROM Parent p")
public class Parent implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private ParentPK id;
@Column(length=10)
private String parentcol;
//bi-directional one-to-one association to Child
@OneToOne(mappedBy="parent")
private Child child;
public Parent() {
}
/* getters and setters */
}
@Embeddable
public class ParentPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(unique=true, nullable=false, length=10)
private String code;
@Column(unique=true, nullable=false)
private int id;
/* getters and setters */
/** Overridden equals and hashcode **/
}
@Entity
@Table(name="child")
@NamedQuery(name="Child.findAll", query="SELECT c FROM Child c")
public class Child implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private ChildPK id;
@Column(nullable=false, length=10)
private String childcol;
//bi-directional one-to-one association to Parent
@OneToOne
@JoinColumns({
@JoinColumn(name="code", referencedColumnName="code", nullable=false, insertable=false, updatable=false),
@JoinColumn(name="id", referencedColumnName="id", nullable=false, insertable=false, updatable=false)
})
private Parent parent;
/* getters and setters */
}
@Embeddable
public class ChildPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(insertable=false, updatable=false, unique=true, nullable=false, length=10)
private String code;
@Column(insertable=false, updatable=false, unique=true, nullable=false)
private int id;
/* overridden equals and hashcode */
Я использую данные Spring для сохранения своих объектов, как показано ниже. Родительская таблица состоит из записи с кодом «код» и идентификатором 1.
Child child = new Child();
ChildPK childPK = new ChildPK();
childPK.setCode("code");
childPK.setId(1);
child.setId(childPK);
child.setChildcol("child1");
childRepository.save(child);
Это удается с 1-го запуска, когда он должен вставить новую запись. Но проблема возникает при втором запуске, когда необходимо обновить, скажем, с помощью
child.setChildcol("child2");
я столкнулся с ошибкой
HHH000327: Error performing load command : org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.xebia.eTechLog.entities.Parent. Expected: class com.xebia.eTechLog.entities.ParentPK, got class com.xebia.eTechLog.entities.ChildPK
Если я попытаюсь указать ссылку ParentPk в дочерней таблице как
@Entity
@Table(name="child")
@NamedQuery(name="Child.findAll", query="SELECT c FROM Child c")
public class Child implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private ParentPK id;
@Column(nullable=false, length=10)
private String childcol;
//bi-directional one-to-one association to Parent
@OneToOne
@JoinColumns({
@JoinColumn(name="code", referencedColumnName="code", nullable=false, insertable=false, updatable=false),
@JoinColumn(name="id", referencedColumnName="id", nullable=false, insertable=false, updatable=false)
})
private Parent parent;
Это работает, но не будет, если в родительском классе будет больше полей, что является моим реальным сценарием.