1
I have a class mapped with Hibernate, however, when saving an object is cascateado the whole object to the child table (what is expected). The problem is that equal objects are saved instead of just relating the child object to the parent object.
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@Fetch(value = FetchMode.SELECT)
private List<Atributo> atributos;
I believed that putting equals
would be enough for the API but did not work as expected.
Does anyone know how to do it in such a way that they don’t need to check if the object exists in the bank every time the function is called?
In the example I made was like this:
@Entity
public class TestePai implements Serializable {
@Id
@GeneratedValue
private Long ID;
String name;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
TesteFilho testefilho;
}
@Entity
public class TesteFilho implements Serializable {
@Id
@GeneratedValue
private Long ID;
String name;
}
I used a task to perform.
@Component
public class TesteScheduller {
private static final Logger log = LoggerFactory.getLogger(UserAdminConfig.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Autowired
TestePaiRepository testePaiRepository;
@Autowired
TesteFilhoRepository testeFilhoRepository;
@Scheduled(initialDelay = 2000L, fixedRate = 24 * 60 * 60 * 1000L)
public void teste() {
log.trace("\n\n********************************************************************\n\n");
log.trace("Start TesteScheduller in: {}", dateFormat.format(new Date()));
TestePai pai = new TestePai();
TesteFilho filho = new TesteFilho();
if (this.testeFilhoRepository.findOneByName(filho.getName()) != null) {
filho = this.testeFilhoRepository.findOneByName(filho.getName());
}
pai.setTestefilho(filho);
log.trace("Pai 1:\n" + pai);
testePaiRepository.saveAndFlush(pai);
log.trace("\n\n********************************************************************\n\n");
pai = new TestePai();
pai.setName("Bom dia");
filho = new TesteFilho();
if (this.testeFilhoRepository.findOneByName(filho.getName()) != null) {
filho = this.testeFilhoRepository.findOneByName(filho.getName());
}
pai.setTestefilho(filho);
log.trace("Pai 1:\n" + pai);
testePaiRepository.save(pai);
testePaiRepository.saveAndFlush(pai);
}
}
This returns me the following error:
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.andersoney.teste.model.Teste.TesteFilho; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.andersoney.teste.model.Teste.TesteFilho
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:299)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:503)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:209)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy95.saveAndFlush(Unknown Source)
at com.andersoney.teste.scheduller.TesteScheduller.teste(TesteScheduller.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
The main challenge in the real situation that I will apply what is discovered here: the object will have many children, a list ManytoMany
, and in this list there will be both objects that exist, as well as objects other than on the bench. I can do the check as above and add the object already with the ID
bank defined. But the foreign key you have must persist ID
, and those who do not, must be saved and obtained the foreign key as the Hibernate already does.
Attributes of child/parent objects are changed, or zeroed, if they are
new
? For that is the only way they can be inserted again, in my opinion.– Gustavo Cinque
Gustavo, what I hope is the behavior contrary to this. I want the data to be checked if it exists in the database and then save.
– Andersoney Rodrigues