【问题标题】:MS SQL : ID(int) works but rowguid (uniqueidentifier) fails for JPA INSERT operationMS SQL:ID(int) 有效,但 JPA INSERT 操作的 rowguid (uniqueidentifier) 失败
【发布时间】:2015-04-14 14:34:13
【问题描述】:

我需要使用 uniqueidentifier 作为每个表的主键,而不是 ID(整数)。下面描述的逻辑适用于 ID(Integer),而不适用于 rowguid(uniqueidentifier)。

我在(MS SQL Server)数据库中有以下表格。

CREATE TABLE Person(
        [ROWGUID] [uniqueidentifier] ROWGUIDCOL  NOT NULL CONSTRAINT             [DF_PERSON_ROWGUID]  DEFAULT (newsequentialid()),
        [NICKNAME] [varchar](15) NULL,
        [EMAIL] [varchar](50) NULL,
        [DATE_OF_BIRTH] [date] NULL)


 CREATE TABLE School(
            [ROWGUID] [uniqueidentifier] ROWGUIDCOL  NOT NULL CONSTRAINT             [DF_PERSON_ROWGUID]  DEFAULT (newsequentialid()),
            [PERSONID] [varchar](15) NULL,
            [EMAIL] [varchar](50) NULL,
            [DATE_OF_BIRTH] [date] NULL)

这是一对多的关系(一个人可能有多个学校)。 School 表的 PERSONID 是 Person 表的 ROWGUID。

在 JPA 方面,问题在于,我无法使用 school 插入 Person 对象。但是,我可以

  • 将 Person 对象单独插入到表中,
  • 为一个人创建一个选择语句并检索其学校。所以我相信它证明了 FK 关系很好。

回到我无法插入的问题;尝试坚持时出现以下异常;

无法将值 NULL 插入“PERSONID”列、“SCHOOL”表;列不允许空值。插入失败。

所以基本上,它不能创建一个 Person 对象,生成它的 ROWGUID,然后将它连接到表 School 的 PERSONID 列。这就是我的假设。我相信这是因为我在 JPA 端生成 ID 的方式。这是怎么回事;

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ROWGUID", columnDefinition = "uniqueidentifier")
    private String rowguid;
    ...


public class School implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ROWGUID", columnDefinition="uniqueidentifier")
    private String rowguid;

//bi-directional many-to-one association to Person
    @ManyToOne
    @JoinColumn(name="PROFILEID")
    private Person person;

    public School() {
    }
    ...

知道如何克服它吗?

重要提示:当每个实体的主键为 ID(int) 时,相同的逻辑可以正常工作,如下所示;

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="ID")
    private int id;


 public class School implements Serializable {
        private static final long serialVersionUID = 1L;

      @Id
      @GeneratedValue(strategy=GenerationType.IDENTITY)
      @Column(name="ID")
      private int id;

    //bi-directional many-to-one association to Person
        @ManyToOne
        @JoinColumn(name="PROFILEID")
        private Person person;

        public School() {
        }

我转换下一代ID的时候基本有问题;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="ID")
    private int id;

进入

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ROWGUID", columnDefinition="uniqueidentifier")
    private String rowguid;

【问题讨论】:

  • 如果你的 Person 总是需要上学,你可以使用@Inheritance(strategy = InheritanceType.JOINED)。基本上 School 扩展了 Person(但这可能是一个糟糕的设计)
  • 请注意,并非所有 JPA 实现都是相同的。我假设您使用 OpenJPA2。我认为您只需要从 School 中删除“@GeneratedValue(strategy = GenerationType.IDENTITY)”。并将 Person 中的关系定义为 @ManyToMany(mappedBy="person")
  • Jama,是的,它是 openJpa。但是为什么要改变关系呢?你认为是一对多造成的问题?
  • 是的。我认为在 Hibernate 中你可以指定外键注释(或类似的东西)。但是在 OpenJPA 中,您必须在 Parent 对象中使用 @ManyToMany(mappedBy="person"),并在 Child 对象中描述映射。 99% 肯定这是唯一的方法(不同的策略除外)。我试图解决同样的问题一段时间。

标签: java sql sql-server jpa


【解决方案1】:

这是一个标准实现:

父子关系(Parent 中的 PK,Child 表中的 FK):

@Entity(name ="Parent")
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private String parentID;

    @ManyToMany(mappedBy = "parent") 
    private List<Child> children;
}

@Entity(name ="Child")
public class Child{
    @Id
    private String parentID;

    @ManyToMany
    @JoinColumn(name="parentID")
    private Parent parent;
}

我认为您的设计可能存在问题。 “无法将值 NULL 插入到列‘PERSONID’、表‘SCHOOL’中;” 将 PersonID 放在 School 表中听起来很奇怪。

【讨论】:

  • Jama,我可能忘记强调“ROWGUID” - 唯一标识符。当我使用 "ID" 整数而不是 rowguid (uniqueidentifier) 复制确切的场景时,我完全没有问题。一对多关系完美运行! .当我将 ID (Integer) 转换为 rowguid (uniqueidentifier) 时,就会出现问题。我将编辑我的问题并提供更多详细信息。
  • 我猜是有误会。我不是想把一个人放进 SCHOOL 。我正在尝试创建一个带有学校的人员对象并将其放入人员表中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多