JPA Hibernate를 사용하여 자동으로 자식 개체 저장
부모와 자식 테이블 사이에 일대 다 관계가 있습니다. 부모 개체에는
List<Child> setChildren(List<Child> childs)
또한 Child 테이블에 외래 키가 있습니다. 이 외래 키는 데이터베이스의 상위 행을 참조하는 ID입니다. 따라서 내 데이터베이스 구성 에서이 외래 키는 NULL이 될 수 없습니다. 또한이 외래 키는 Parent 테이블의 기본 키입니다.
그래서 내 질문은 다음과 같은 작업을 수행하여 자동으로 자식 개체를 저장하는 방법입니다.
session.save(parent);
위의 작업을 시도했지만 Child 테이블의 외래 키 필드가 NULL이 될 수 없다는 내용의 데이터베이스 오류가 발생합니다. JPA에이 외래 키를 자동으로 자식 개체에 설정하도록 지시하여 자식 개체를 자동으로 저장할 수 있습니까?
미리 감사드립니다.
위의 작업을 시도했지만 Child 테이블의 외래 키 필드가 NULL이 될 수 없다는 내용의 데이터베이스 오류가 발생합니다. JPA에이 외래 키를 자동으로 자식 개체에 설정하도록 지시하여 자식 개체를 자동으로 저장할 수 있습니까?
여기에 두 가지가 있습니다.
첫째, 저장 작업을 계단식으로 작성해야합니다 (하지만 내 이해는이 작업을 수행하고 있거나 "하위"테이블에 삽입하는 동안 FK 제약 조건 위반이 발생하지 않는다는 것입니다)
둘째, 아마도 양방향 연관성이 있고 "링크의 양면"을 올바르게 설정하지 않은 것 같습니다. 다음과 같이해야합니다.
Parent parent = new Parent();
...
Child c1 = new Child();
...
c1.setParent(parent);
List<Child> children = new ArrayList<Child>();
children.add(c1);
parent.setChildren(children);
session.save(parent);
일반적인 패턴은 링크 관리 방법을 사용하는 것입니다.
@Entity
public class Parent {
@Id private Long id;
@OneToMany(mappedBy="parent")
private List<Child> children = new ArrayList<Child>();
...
protected void setChildren(List<Child> children) {
this.children = children;
}
public void addToChildren(Child child) {
child.setParent(this);
this.children.add(child);
}
}
그리고 코드는 다음과 같습니다.
Parent parent = new Parent();
...
Child c1 = new Child();
...
parent.addToChild(c1);
session.save(parent);
참고 문헌
- Hibernate Core 참조 가이드
xml / annotation을 통해 매핑에서 캐스케이드 옵션을 설정해야한다고 생각합니다. 여기 에서 Hibernate 참조 예제를 참조하십시오 .
주석을 사용하는 경우 다음과 같이해야합니다.
@OneToMany(cascade = CascadeType.PERSIST) // Other options are CascadeType.ALL, CascadeType.UPDATE etc..
양방향 관계의 자식 개체에 부모 개체를 할당하는 방법은 다음과 같습니다.
일대 다라는 관계가 있다고 가정하면 각 상위 개체에 대해 하위 개체 집합이 존재합니다. 양방향 관계에서 각 자식 개체는 부모에 대한 참조를 갖습니다.
eg : Each Department will have list of Employees and each Employee is part of some department.This is called Bi directional relations.
이를 달성하기 위해 한 가지 방법 은 부모 개체를 유지하면서 자식 개체에 부모를 할당하는 것입니다.
Parent parent = new Parent();
...
Child c1 = new Child();
...
c1.setParent(parent);
List<Child> children = new ArrayList<Child>();
children.add(c1);
parent.setChilds(children);
session.save(parent);
다른 방법 은 하이버 네이트 인터셉터를 사용하여 할 수 있다는 것입니다.이 방법은 모든 모델에 대해 위의 코드를 작성하지 않도록 도와줍니다.
Hibernate 인터셉터는 DB 작업을 수행하기 전에 자신의 작업을 수행 할 수있는 API를 제공합니다. 객체의 onSave와 마찬가지로 리플렉션을 사용하여 자식 객체에 부모 객체를 할당 할 수 있습니다.
public class CustomEntityInterceptor extends EmptyInterceptor {
@Override
public boolean onSave(
final Object entity, final Serializable id, final Object[] state, final String[] propertyNames,
final Type[] types) {
if (types != null) {
for (int i = 0; i < types.length; i++) {
if (types[i].isCollectionType()) {
String propertyName = propertyNames[i];
propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
try {
Method method = entity.getClass().getMethod("get" + propertyName);
List<Object> objectList = (List<Object>) method.invoke(entity);
if (objectList != null) {
for (Object object : objectList) {
String entityName = entity.getClass().getSimpleName();
Method eachMethod = object.getClass().getMethod("set" + entityName, entity.getClass());
eachMethod.invoke(object, entity);
}
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
return true;
}
}
그리고 Intercepter를 구성에 등록 할 수 있습니다.
new Configuration().setInterceptor( new CustomEntityInterceptor() );
다음 프로그램은 최대 절전 모드에서 양방향 관계가 작동하는 방식을 설명합니다. 부모가 저장하면 자식 개체 목록이 자동으로 저장됩니다.
@Entity
@Table(name="clients")
public class Clients implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@OneToMany(mappedBy="clients", cascade=CascadeType.ALL)
List<SmsNumbers> smsNumbers;
on the parent side
and put the following annotation on the child side
@Entity
@Table(name="smsnumbers")
public class SmsNumbers implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
String number;
String status;
Date reg_date;
@ManyToOne
@JoinColumn(name = "client_id")
private Clients clients;
and getter setter.
public static void main(String arr[])
{
Session session = HibernateUtil.openSession();
//getting transaction object from session object
session.beginTransaction();
Clients cl=new Clients("Murali", "1010101010");
SmsNumbers sms1=new SmsNumbers("99999", "Active", cl);
SmsNumbers sms2=new SmsNumbers("88888", "InActive", cl);
SmsNumbers sms3=new SmsNumbers("77777", "Active", cl);
List<SmsNumbers> lstSmsNumbers=new ArrayList<SmsNumbers>();
lstSmsNumbers.add(sms1);
lstSmsNumbers.add(sms2);
lstSmsNumbers.add(sms3);
cl.setSmsNumbers(lstSmsNumbers);
session.saveOrUpdate(cl);
session.getTransaction().commit();
session.close();
Use org.hibernate.annotations
for doing Cascade
, if the hibernate
and JPA
are used together , its somehow complaining on saving the child objects.
in your setChilds, you might want to try looping thru the list and doing something like
child.parent = this;
you also should set up the cascade on the parent to the appropriate values.
In short set cascade type to all , will do a job; For an example in your model. Add Code like this . @OneToMany(mappedBy = "receipt", cascade=CascadeType.ALL) private List saleSet;
참고URL : https://stackoverflow.com/questions/3927091/save-child-objects-automatically-using-jpa-hibernate
'UFO ET IT' 카테고리의 다른 글
값이없는 테이블에 삽입하기위한 구문? (0) | 2020.11.24 |
---|---|
WordPress MVC를 준수합니까? (0) | 2020.11.24 |
MySQL의 DOUBLE 대 DECIMAL (0) | 2020.11.24 |
여러 모델 하위 클래스의 Backbone.js 컬렉션 (0) | 2020.11.24 |
자바 동기화 목록 (0) | 2020.11.24 |