簡體   English   中英

使用 JPA Hibernate 自動保存子對象

[英]Save child objects automatically using JPA Hibernate

我在 Parent 和 Child 表之間有一個一對多的關系。 在父對象中我有一個

List<Child> setChildren(List<Child> childs)

我在 Child 表中也有一個外鍵。 此外鍵是引用數據庫中父行的 ID。 所以在我的數據庫配置中這個外鍵不能為NULL。 此外鍵也是父表中的主鍵。

所以我的問題是如何通過執行以下操作自動保存子對象:

session.save(parent);

我嘗試了上面的方法,但我收到一個數據庫錯誤,抱怨 Child 表中的外鍵字段不能為 NULL。 有沒有辦法告訴 JPA 自動將這個外鍵設置到 Child 對象中,以便它可以自動保存子對象?

我嘗試了上述操作,但出現數據庫錯誤,抱怨 Child 表中的外鍵字段不能為 NULL。 有沒有辦法告訴 JPA 自動將此外鍵設置到 Child 對象中,以便它可以自動保存子對象?

嗯,這里有兩件事。

首先,您需要級聯保存操作(但我的理解是您正在執行此操作,否則在“子”表中插入期間不會出現 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.addToChildren(c1);

session.save(parent);
參考

我相信您需要通過 xml/annotation 在映射中設置級聯選項。 請參閱此處的 Hibernate 參考示例

如果您使用注釋,則需要執行以下操作,

@OneToMany(cascade = CascadeType.PERSIST) // Other options are CascadeType.ALL, CascadeType.UPDATE etc..

以下程序描述了雙向關系如何在休眠中工作。

當父對象保存其子對象列表時,將自動保存。

在父母方面:

    @Entity
    @Table(name="clients")
    public class Clients implements Serializable  {

         @Id
         @GeneratedValue(strategy = GenerationType.IDENTITY)     
         @OneToMany(mappedBy="clients", cascade=CascadeType.ALL)
          List<SmsNumbers> smsNumbers;
    }

並在子端添加以下注釋:

  @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();    

 }

在您的 setChilds 中,您可能想嘗試遍歷列表並執行類似的操作

child.parent = this;

您還應該將父級上的級聯設置為適當的值。

以下是在雙向關系的子對象中分配父對象的方法?

假設您有一個關系說一對多,那么對於每個父對象,存在一組子對象。 在雙向關系中,每個子對象都將引用其父對象。

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 攔截器提供 apis 來完成您自己的工作。同樣,對象的保存,我們可以使用反射在子對象中分配父對象。

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;
    }

}

您可以將攔截器注冊為配置

new Configuration().setInterceptor( new CustomEntityInterceptor() );

在 JPA @*To*關系中,父實體和子實體必須在(父)保存之前交叉分配。

使用org.hibernate.annotations進行Cascade ,如果hibernateJPA一起使用,它會以某種方式抱怨保存子對象。

總之將級聯類型設置為 all ,就可以了; 以您的模型為例。 像這樣添加代碼。 @OneToMany(mappedBy = "receipt", cascade=CascadeType.ALL) 私有列表 saleSet;

如果您沒有雙向關系並且只想保存/更新子表中的單列,那么您可以使用子實體創建 JPA 存儲庫並調用 save/saveAll 或 update 方法。

注意:如果您遇到 FK 違規,則意味着您的郵遞員請求具有主鍵和外鍵 ID 與子表中生成的 ID 不匹配,請檢查您要更新的請求和子表中的 ID(它們應該匹配/如果它們並不意味着您遇到 FK 違規)在事務之前保存父級和子級時生成的任何 id,當您嘗試更新子表中的單個列時,這些 id 應該在您的第二次調用中匹配。

家長:

@Entity
@Table(name="Customer")
public class Customer implements Serializable  {

     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)  
     private UUID customerId ;
     
     @OneToMany(cascade = CascadeType.ALL) 
     @JoinColumn(name ="child_columnName", referencedColumnName= 
                "parent_columnName")
     List<Accounts> accountList;
}

孩子 :

 @Entity
    @Table(name="Account")
    public class Account implements Serializable  {

         @Id
         @GeneratedValue(strategy = GenerationType.IDENTITY)  
         private UUID accountid;
         
        
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM