Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate UniqueConstraint允许多个列具有空值_Hibernate_Jpa_Unique Constraint - Fatal编程技术网

Hibernate UniqueConstraint允许多个列具有空值

Hibernate UniqueConstraint允许多个列具有空值,hibernate,jpa,unique-constraint,Hibernate,Jpa,Unique Constraint,我遇到了一个问题,无法将重复的值插入MySQL数据库(使用Hibernate)。问题是:我有一个类别,它有一个父类别。可以有两个名称相同但父级不同的类别(这就是类别名称不能用作businessId的原因)。当类别没有父类别(即顶级类别)时,parentId的值为NULL。我无法理解我在以下代码中犯了什么错误,以便将重复的代码插入到数据库中 这是我的实体类 @Entity @Table(name = "category", uniqueConstraints = {@UniqueConstrain

我遇到了一个问题,无法将重复的值插入MySQL数据库(使用Hibernate)。问题是:我有一个类别,它有一个父类别。可以有两个名称相同但父级不同的类别(这就是类别名称不能用作businessId的原因)。当类别没有父类别(即顶级类别)时,parentId的值为NULL。我无法理解我在以下代码中犯了什么错误,以便将重复的代码插入到数据库中

这是我的实体类

@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