简体   繁体   English

删除对象时使用Hibernate违反MS-SQL中的UNIQUE KEY约束

[英]Violation of UNIQUE KEY constraint in MS-SQL using Hibernate when deleting objects

The application we have used MySQL until today and everything was fine. 直到今天,我们一直使用MySQL的应用程序一切都很好。 Now we need to use MSSQL. 现在我们需要使用MSSQL。

A lot of our unit tests are now failing. 我们的许多单元测试现在都失败了。 A sample is as follows: 示例如下:

Caused by: java.sql.BatchUpdateException: 
Violation of UNIQUE KEY constraint 'UQ__field_ty__5068257C6DE5E37D'. 
Cannot insert duplicate key in object 'dbo.field_type_mapping'. 
The duplicate key value is (<NULL>, -11).

As I said, this test is successful when using MySQL. 就像我说的那样,使用MySQL时此测试成功。

The table field_type_mapping has a constraint: field_type_mapping有一个约束:

/****** Object:  Index [UQ__field_ty__5068257C6DE5E37D]
ALTER TABLE [dbo].[field_type_mapping] ADD UNIQUE NONCLUSTERED 
(
    [mapping_entity_id] ASC,
    [field_type_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

The test is as follows and the exception is thrown at the last line of this test: 测试如下,并且在测试的最后一行抛出异常:

Invoice document = documentDao.get(5000);
assertEquals("Document should have exactly one reference field!", 1, document.getFieldTypeMappings().size());
assertEquals("Document should have exactly one item!", 1, document.getDocumentItems().size());

Set<InvoiceItem> items = document.getDocumentItems();
InvoiceItem item = items.iterator().next();
assertEquals("Document's item should have no reference field!", 0, item.getFieldTypeMappings().size());

ReferenceFieldType referenceFieldType = referenceFieldTypeDao.get(-11L);
FieldTypeMapping documentFieldType = new FieldTypeMapping();
documentFieldType.setFieldType(referenceFieldType);
documentFieldType.setFieldValue("a value");
document.addFieldTypeMapping(documentFieldType);

FieldTypeMapping documentItemFieldType = new FieldTypeMapping();
documentItemFieldType.setFieldType(referenceFieldType);
documentItemFieldType.setFieldValue("another value");
item.addFieldTypeMapping(documentItemFieldType);
documentDao.save(document);
flush();

document = documentDao.get(id);
assertEquals("Reference object for document not added!", 2, document.getFieldTypeMappings().size());
items = document.getDocumentItems();
item = items.iterator().next();
assertEquals("Reference object for document item not added!", 1, item.getFieldTypeMappings().size());

document.addFieldTypeMapping(documentFieldType);
item.addFieldTypeMapping(documentItemFieldType);
documentDao.save(document);
flush();

document = documentDao.get(id);
assertEquals("Number of reference object should not have changed for document!", 2, document.getFieldTypeMappings().size());
items = document.getDocumentItems();
item = items.iterator().next();
assertEquals("Number of reference object should not have changed for document' item!", 1, item.getFieldTypeMappings().size());

document.getFieldTypeMappings().remove(documentFieldType);
item.getFieldTypeMappings().remove(documentItemFieldType);
documentDao.save(document);
flush();  // Exception is thrown at this point..

My understanding is something is wrong with: 我的理解是:

item.getFieldTypeMappings().remove(documentItemFieldType);

as the exception is mentioning id -11 ? 例外是提到id -11?

The hibernate code for removal is as follows: 待删除的休眠代码如下:

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
        org.hibernate.annotations.CascadeType.DETACH,
        org.hibernate.annotations.CascadeType.LOCK})
@JoinColumn(name = "mapping_entity_id")
@XmlTransient
@Fetch(FetchMode.SELECT)
public Set<FieldTypeMapping> getFieldTypeMappings() {
    return fieldTypeMappings;
}

As I am pretty novice with this I do not even understand what might be wrong. 因为我是个新手,所以我什至不了解可能出了什么问题。 How can I fix this issue? 如何解决此问题? Is this an issue with hibernate and how it handles the queries? 这是休眠的问题吗?它如何处理查询? I also want to mention that all the db is created with hibernate as well, no manual sql execution and db creation is made. 我还想提到,所有数据库也是使用休眠模式创建的,没有手动执行SQL和数据库创建。

You usually need the ability to have a null FK when you may not know the value at the time of entering the data, especially whilst you know other values to be entered. 当您在输入数据时可能不知道值,特别是在您知道要输入其他值时,通常需要具有FK为空的功能。

To allow nulls in an FK generally all you have to do is allow nulls on the field that has the FK. 要在FK中允许空值,通常要做的就是在具有FK的字段上允许空值。 The null value is separate from the idea of it being an FK. 空值与其作为FK的想法是分开的。 - This is what I believe you need to do. -我认为这是您需要做的。

Whether it is unique or not unique relates to whether the table has a one-one or a one-many relationship to the parent table. 它是否唯一与表是否与父表具有一对一或一对多的关系有关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM