Hibernate:不能使用CascadeType.PERSIST

时间:2015-03-31 18:48:51

标签: java hibernate jpa

我的数据库类别和项目中有很多与很多相关。 我的目标是当我将项目添加到类别中的项目列表时,这些项目将自动添加到数据库中。 我认为通过CascadeType.PERSIST对类别中的项目列表进行注释将完成工作,但事实并非如此。放入所有CascaseTypes枚举值也不起作用。 每次提交事务时我都会收到以下异常:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: il.co.site_building.webutils.shop.Item

只有当我使用CascadeType.ALL对其进行注释时,才能正确保存这些项目。

类别的代码:

public Category(Integer uid,
                  String name,
                  String displayName,
                  Category parent,
                  List<Category> subCategories,
                  List<Item> items){
    m_uid             = uid;
    m_name            = name;
    m_displayName     = displayName;
    m_parent          = parent;
    m_subCategories   = subCategories;
    m_itemsInCategory = items != null ? items : new LinkedList<>();
  }

  @ManyToMany(cascade = CascadeType.PERSIST) //Doesn't work. Only CascadeType.ALL will work.
  @JoinTable(name = "items_categories",
             joinColumns = {@JoinColumn(name="category") },
             inverseJoinColumns = {@JoinColumn(name = "item")})
  public List<Item> getItemsInCategory(){return m_itemsInCategory;}

项目的代码:

public Item(Integer uid,
              String name,
              String displayName,
              String description,
              BigDecimal price,
              Integer orderIndex,
              String serialNo,
              AttributeType attributeType,
              List<ItemAttribute> itemAttributes,
              List<Category> categories){
    m_uid            = uid;
    m_name           = name;
    m_displayName    = displayName;
    m_description    = description;
    m_price          = price.setScale(PRICE_SCALE);
    m_orderIndex     = orderIndex;
    m_serialNo       = serialNo;
    m_attributeType  = attributeType;
    m_itemAttributes = itemAttributes != null ? itemAttributes : new LinkedList<>();
    m_categories     = categories != null? categories : new LinkedList<>();
  }

@ManyToMany(mappedBy = "itemsInCategory")
  public List<Category> getCategories(){return m_categories;}

插入项目的代码(假设类别已存在):

public static final String SHIRT_NAME = "shirt";
public static final String SHIRT_DISPLAY_NAME = "shirt display";
public static final String SHIRT_DESCRIPTION = "shirt description";
public static final BigDecimal SHIRT_PRICE = new BigDecimal("2.01");
public static final Integer SHIRT_ORDER_INDEX = 1;
public static final String SHIRT_SERIAL_NUMBER = "shirt_sn";

public static final Item SHIRT = new Item(null,
                                          SHIRT_NAME,
                                          SHIRT_DISPLAY_NAME,
                                          SHIRT_DESCRIPTION,
                                          SHIRT_PRICE,
                                          SHIRT_ORDER_INDEX,
                                          SHIRT_SERIAL_NUMBER,
                                          AttributeTypeTest.ATTRIBUTE_TYPE_SIZE,
                                          null, null);
session.beginTransaction();
Query query.setParameter("uid", CategoryTest.CATEGORY_SHIRTS.getUid()); //This category was persisted properly somewhere else
Category category = (Category)query.uniqueResult();
List<Item> itemsInCategory = category.getItemsInCategory();
SHIRT.getCategories().add(category); itemsInCategory.add(SHIRT);
session.getTransaction().commit();

1 个答案:

答案 0 :(得分:1)

因此在使用带有JPA注释类的本机API时会出现Hibernate问题。

当使用CascadeType.PERSIST注释关系时,Hibernate不会持久保存子对象,但仅适用于CascadeType.ALL注释关系。

但是,如果您通过JPA API使用Hibernate(因此EntityManger而不是Session,其余代码几乎完全相同), 然后,CascadeType.PERSISTCascadeType.ALL都会触发子元素的持久性。这显然是JPA规范的一部分(感谢Chris指出它),即使它在javadocs中被省略了。 我总是错误地认为只有明确的persist()请求是级联的。

如果您的项目还不晚,您可以考虑使用JPA标准而不是hibernate API。对于新代码,转换几乎是无缝的(持久而不是保存,删除而不是删除....)