Hello, I need to establish a one-to-one relationship between classes A and B. Where case A is the owner of the relation and when assigning from call B the value is lost. I leave you an example project.
Thank you
Hello, I need to establish a one-to-one relationship between classes A and B. Where case A is the owner of the relation and when assigning from call B the value is lost. I leave you an example project.
Thank you
package com.company.sampleonetoone.entity;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.OneToOne;
import com.haulmont.cuba.core.entity.StandardEntity;
@Table(name = "SAMPLEONETOONE_B")
@Entity(name = "sampleonetoone$B")
public class B extends StandardEntity {
private static final long serialVersionUID = -6636144354361612238L;
@Column(name = "FIELD1")
protected String field1;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "b")
protected A a;
public void setField1(String field1) {
this.field1 = field1;
}
public String getField1() {
return field1;
}
public void setA(A a) {
this.a = a;
}
public A getA() {
return a;
}
}
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import com.haulmont.cuba.core.entity.StandardEntity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
@Table(name = "SAMPLEONETOONE_A")
@Entity(name = "sampleonetoone$A")
public class A extends StandardEntity {
private static final long serialVersionUID = -3492608347267339251L;
@Column(name = "FIELD1", nullable = false)
protected String field1;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "B_ID")
protected B b;
public void setB(B b) {
this.b = b;
}
public B getB() {
return b;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField1() {
return field1;
}
}
an example
an example
As workaround i do the next
package com.company.sampleonetoone.listener;
import com.company.sampleonetoone.entity.A;
import com.haulmont.cuba.core.Persistence;
import org.springframework.stereotype.Component;
import com.haulmont.cuba.core.listener.BeforeInsertEntityListener;
import com.haulmont.cuba.core.EntityManager;
import com.company.sampleonetoone.entity.B;
import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener;
import com.haulmont.cuba.core.listener.AfterInsertEntityListener;
import java.sql.Connection;
import com.haulmont.cuba.core.listener.AfterUpdateEntityListener;
import javax.inject.Inject;
import com.haulmont.cuba.core.listener.BeforeDeleteEntityListener;
@Component("sampleonetoone_BListener")
public class BListener implements BeforeInsertEntityListener<B>, BeforeUpdateEntityListener<B>, BeforeDeleteEntityListener<B> {
@Inject
protected Persistence persistence;
@Override
public void onBeforeInsert(B entity, EntityManager entityManager) {
if(entity.getA()!=null){
A a= entityManager.find(entity.getA().getClass(),entity.getA().getUuid());
a.setB(entity);
entityManager.persist(a);
}
}
@Override
public void onBeforeUpdate(B entity, EntityManager entityManager) {
A aold= (A) persistence.getTools().getOldValue(entity, "a");
if(aold!=null && (entity.getA()==null || aold.getUuid()!= entity.getA().getUuid())){
aold.setB(null);
entityManager.persist(aold);
}
if(entity.getA()!=null){
A a= entityManager.find(A.class,entity.getA().getUuid());
a.setB(entity);
entityManager.persist(a);
}
}
@Override
public void onBeforeDelete(B entity, EntityManager entityManager) {
A aold= entity.getA();
if(aold!=null){
aold.setB(null);
entityManager.persist(aold);
}
}
}
JPA saves relations only from owning side. What about changing the model to make the needed side (or both sides) owning?
Thanks for your answer. My solution does not look elegant. But table A is large and I need the field of relation B to be in table A. Can an ONETOONE association have Both Owning Side? how can I do it?
Yes you can have both sides owning, i.e. having a foreign key column. The current version of Studio does not support it, but you can do it in the entity source code. Just remove the mappedBy attribute from the @OneToOne annotation and add the @JoinColumn annotation, for example:
@Table(name = "SAMPLE_BAR")
@Entity(name = "sample$Bar")
public class Bar extends StandardEntity {
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "FOO_ID")
protected Foo foo;
After that Studio will generate correct database scripts including your manually defined FOO_ID column.