Hibernate UniqueConstraint允许多个列具有空值
我遇到了一个问题,无法将重复的值插入MySQL数据库(使用Hibernate)。问题是:我有一个类别,它有一个父类别。可以有两个名称相同但父级不同的类别(这就是类别名称不能用作businessId的原因)。当类别没有父类别(即顶级类别)时,parentId的值为NULL。我无法理解我在以下代码中犯了什么错误,以便将重复的代码插入到数据库中 这是我的实体类Hibernate UniqueConstraint允许多个列具有空值,hibernate,jpa,unique-constraint,Hibernate,Jpa,Unique Constraint,我遇到了一个问题,无法将重复的值插入MySQL数据库(使用Hibernate)。问题是:我有一个类别,它有一个父类别。可以有两个名称相同但父级不同的类别(这就是类别名称不能用作businessId的原因)。当类别没有父类别(即顶级类别)时,parentId的值为NULL。我无法理解我在以下代码中犯了什么错误,以便将重复的代码插入到数据库中 这是我的实体类 @Entity @Table(name = "category", uniqueConstraints = {@UniqueConstrain
@Entity
@Table(name = "category", uniqueConstraints = {@UniqueConstraint(columnNames = {"name","parentId"})})
public class Category implements Serializable {
@Id
@Column(name="id")
@GeneratedValue
private long id;
@Column(name="name")
private String name;
@ManyToOne(cascade={CascadeType.ALL})
@JoinColumn(name="parentId", nullable=true)
private Category parent;
...
}
下面是用于解析新类别的代码(我相信这里有问题:-|)
这是insertCategory函数
public Category insertCategory (Category category) {
Session session = sessionFactory.openSession();
Transaction transaction = null;
try{
transaction = session.beginTransaction();
category.setId((Long) session.save(category));
transaction.commit();
} catch (HibernateException e) {
if (transaction!=null)
transaction.rollback();
...
} finally {
session.close();
}
return category;
}
执行代码后,我在数据库中获得以下条目:
select * from category;
+----+--------------+----------+
| id | name | parentId |
+----+--------------+----------+
| 1 | A | NULL |
| 4 | A | NULL |
| 2 | B | 1 |
| 3 | C | 2 |
| 5 | B | 4 |
| 6 | C | 5 |
+----+--------------+----------+
当我试图仅通过“名称”进行限制时,只有3个entires被插入到数据库中,但由于上述情况,我不能仅通过名称进行限制
编辑:我所看到的解决这个问题的一个可能性是约束定义中的函数用法(在MySQL中可以是IFNULL(parentId,0)。这种可能性似乎在Oracle中是可能的(根据post),但在MySQL中不可能
编辑2:事实上,我在一些人身上发现了类似的问题。因为我使用的是MySQL,所以我检查了创建表时生成的代码,它与Bug report中的代码几乎相同(根据bugtracker中提到的一些标准,这实际上被认为不是bug。无论如何,我的同事尝试在MS SQL Server上执行等效代码,这实际上阻止了他在name字段和null parentId上插入具有相同值的行。似乎没有数据库级别的可能性(至少使用MySQL)接受答案,因为这是解决这个问题的一个可能的解决办法(使用幻数
,我不会坚持,我更愿意在我的代码中保留一个额外的查找
查询)
任何帮助都将受到感谢,
谢谢!一个简单的解决方案是让
parentId
成为“自我”
因此,您不能有两个“顶级”类别。使parentId
不可为空
我确信你的问题与没有在约束中检查空值有关。尽管你可以尝试使用hibernate检查,但它肯定会更加低效
@org.hibernate.annotations.Check
我发现它与空值有关,我应该使用一些东西使其成为“self”。问题是:P?一个想法是插入“dummy”Category..但我认为这是一个相当丑陋的解决方案..我不确定hibernate是否能够处理一个新实体的持久化,并使用自身的引用…如果不能,只需将连接映射到一个新的Category\u to\u父关系表。Category表将只包含名称(唯一,不可为null).嗯,现在我在代码中添加了一个检查,所以在插入之前我检查它是否存在..但这是一个额外的查询:-|。。
+----+--------------+----------+
| id | name | parentId |
+----+--------------+----------+
| 1 | A | 1 |
| 2 | B | 1 |
| 3 | C | 2 |
| 4 | C | 3 |
+----+--------------+----------+
@org.hibernate.annotations.Check