当前位置: 首页 > 知识库问答 >
问题:

JPA:删除孤儿,无效列

毕和志
2023-03-14

最近,我问了一个关于堆栈溢出的非常类似的问题,这是另一个问题的重复。在另一个问题中,我采用了一种变通方法,解决了我的问题。现在,这一次解决方案不起作用,所有其他提到的解决方案都不起作用。此外,链接到第一个线程的其他线程的所有解决方案都不起作用。

这是我最初的问题:

SQLServerException:无效的列名

这就是重复:

Hibernate列名问题

我已经检查了链接和相关部分右侧的主题,但找不到问题的解决方案。我也无法理解我的问题发生的原因。

我有两个表:Declaration和File(我在这里不提我的其他表,因为它们与问题无关)

CREATE TABLE [dbo].[Declaration] (
    [number]            INT           NOT NULL,
    [status]            VARCHAR (50)  NOT NULL,
    [name]              VARCHAR (50)  NOT NULL,
    [description]       VARCHAR (250) NOT NULL,
    [amount]            FLOAT (53)    NOT NULL,
    [date]              DATE          NOT NULL,
    [period_id]         INT           NOT NULL,
    [client_project_id] INT           NOT NULL,
    PRIMARY KEY CLUSTERED ([number] ASC),
    CONSTRAINT [fk_client_period] FOREIGN KEY ([client_project_id]) REFERENCES [dbo].[ClientProject] ([number]),
    CONSTRAINT [fk_period] FOREIGN KEY ([period_id]) REFERENCES [dbo].[Period] ([number])
);

CREATE TABLE [dbo].[File] (
    [number] INT          NOT NULL,
    [path]   VARCHAR (50) NOT NULL,
        [declaration_id] INT NOT NULL, 
        PRIMARY KEY CLUSTERED ([number] ASC),
CONSTRAINT [fk_file] FOREIGN KEY ([declaration_id]) REFERENCES [dbo].[Declaration] ([number])
    );

具有相应的类别:

@Entity
@Table(name = "[file]")
public class File {

    @Id
    private int number;
    private String path;

    @ManyToOne(targetEntity = Declaration.class)
    private int declaration_id;

    public int getDeclaration_id() {
        return declaration_id;
    }

    public void setDeclaration_id(int declaration_id) {
        this.declaration_id = declaration_id;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

@Entity
public class Declaration {

    @Id
    private int number;
    private String status;
    private String name;
    private String description;
    private double amount;
    private Date date;
    private int period_id;
    private int client_project_id;

    @OneToMany(targetEntity = File.class,mappedBy = "declaration_id",orphanRemoval = true)
    private List<File> files = new ArrayList<>();

    public List<File> getFiles() {
        return files;
    }

    public void setFiles(List<File> files) {
        this.files = files;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number= number;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public int getPeriod_id() {
        return period_id;
    }

    public void setPeriod_id(int period_id) {
        this.period_id = period_id;
    }

    public int getClient_project_id() {
        return client_project_id;
    }

    public void setClient_project_id(int client_project_id) {
        this.client_project_id = client_project_id;
    }
}

我已经根据这些主题和教程定义了我的@ManyToOne和@OneTo很多关系:

https://vladmihalcea.com/a-beginners-guide-to-jpa-and-hibernate-cascade-types/

JPA加入专栏vs maspdBy

我想要的:删除声明,自动删除与声明相关的文件

我得到的:无效的列名“declaration_id_number”。

我所尝试的:

- renaming fields in database to declaration_id_number (results in declaration_id_number_number)
 - using @Column(name="declaration_id") on declaration_id field
 - using @Colum(name="declaration_id") on the getter field
 - using @JoinColumn(name="fk_file") on the declaration_id field 
 - Using different kinds of naming stategies (in application.properties), including the default one

spring.jpa.hibernate.naming.strategy: org.hibernate.cfg.EJB3NamingStrategy
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

实际SQL查询:

select files0_.declaration_id_number as declarat3_3_0_, files0_.number as number1_3_0_, files0_.number as number1_3_1_, files0_.declaration_id_number as declarat3_3_1_, files0_.path as path2_3_1_ from [file] files0_ where files0_.declaration_id_number=?


select declaratio0_.number as number1_2_0_, declaratio0_.amount as amount2_2_0_, declaratio0_.client_project_id as client_p3_2_0_, declaratio0_.date as date4_2_0_, declaratio0_.description as descript5_2_0_, declaratio0_.name as name6_2_0_, declaratio0_.period_id as period_i7_2_0_, declaratio0_.status as status8_2_0_ from declaration declaratio0_ where declaratio0_.number=?

我正在使用JPA Hibernate 5.2.10运行Spring Boot

有没有人知道为什么会这样,如果我知道为什么会这样,我也许可以自己解决这个问题。现在我完全被困住了。

提前谢谢。

编辑:

好的,所以我偶然解决了自己的问题,我仍然不知道为什么会出现这个问题。根据本主题的答案:

JPA加入专栏vs maspdBy

你使用@ManyToOne

在我的例子中,我不需要在File类中使用@ManyToOne。我只需要在我的声明类中使用@OneTo很多。删除此注释后不会再出现错误。

如果有人知道这个问题的原因,请提供一个答案,以便将来对我或其他人有用。

共有1个答案

上官德寿
2023-03-14

在我的例子中,我不需要在File类中使用@ManyToOne。我只需要在我的声明类中使用@OneTo很多。删除此注释后不会再出现错误。

我认为这行不通。如果您删除@ManyToOne注释,持久性提供程序将默认创建一个连接表来维护关系。你的意思可能是你没有得到任何异常。但是看看数据库模式:

CREATE TABLE [dbo].[File] (
    [number] INT          NOT NULL,
    [path]   VARCHAR (50) NOT NULL,
    [declaration_id] INT NOT NULL, 
    PRIMARY KEY CLUSTERED ([number] ASC),
    CONSTRAINT [fk_file] FOREIGN KEY ([declaration_id]) REFERENCES [dbo].[Declaration] ([number])
);
  • 声明id被声明为非空,这意味着除非在声明表中为其分配一个条目,否则无法在此表中保存任何内容
  • 定义了外键约束,这意味着您的数据库将在保存文件记录时对此进行检查

这意味着您有两种选择:

>

您从File表中删除外键字段declaration_id和相应的参照完整性约束。在这种情况下,持久性提供程序将默认为您创建一个连接表,除非您对其进行自定义。

因此,如果您想使用第一个选项,即@ManyToOne注释,您必须将实体映射如下:

@Entity
@Table(name = "[file]")
public class File {

    @Id
    private int number;
    private String path;

    @ManyToOne
    @JoinColumn(name = "declaration_id")
    private Declaration declaration;

    public int getDeclaration_id() {
        return declaration_id;
    }

    // ... getters and setters
}

以及稍加修改的声明实体:

@Entity
public class Declaration {

     @Id
     private int number;
     // ... other fields

    @OneToMany(mappedBy = "declaration",orphanRemoval = true)
    private List<File> files = new ArrayList<>();

   // ... Rest of the code
}

笔记:

  • 我删除了targetEntity=File。类中的属性,因为您不需要它,因为您的集合已经暗示了类型
 类似资料:
  • 问题内容: 我在使用具有以下映射的JPA删除孤立节点时遇到问题 我遇到了孤立角色挂在数据库周围的问题。 我可以使用特定于注释的Hibernate标记,但是显然我不想将解决方案绑定到Hibernate实现中。 编辑 :似乎JPA 2.0将包括对此的支持。 问题答案: 如果将它与Hibernate一起使用,则必须显式定义批注,该批注可与JPA结合使用。 如果您不打算使用Hibernate,则必须先明确

  • 有人知道我为什么会有这种行为吗?是我的代码出了bug还是什么问题?

  • 下面是场景: 容器和项都可以存在排他性。ItemContainer只能包含对现有项和容器的引用 我想要做的是能够删除一个项目,并删除它对应的ItemContainer行(使用孤儿删除)。任何容器都应该仍然存在。 编辑1:正如JB所要求的:下面是正在使用的相关代码。 请求来自一个jsp 值得一提的是,我试图在我的jUnit测试中做同样的事情(如果需要,我可以发布测试代码和任何相关的类),但是我没有收

  • 客户端版本:version.info{Major:“1”,Minor:“0”,GitVersion:“V1.0.4”,GitCommit:“65D28D5FD12345592405714C81CD03B9C41D41D9”,GitTreesteat:“Clean”} 服务器版本:version.info{Major:“1”,Minor:“2”,GitVersion:“V1.2.0”,GitComm

  • 我试图收集以下信息,以便在删除父实体时自动删除子实体。似乎最常见的方法是使用这三种注释中的一种:或或。 我对第三个有点困惑:,因为教义官方留档中关于这个的解释非常少),我希望有人能证实我从我的研究中收集和理解的以下信息网络和经验... 它有什么作用? == 应用于收集(因此在或关系中) == ORM中的实施 可与、或 == 这个策略有点棘手,但可能非常强大和快速。(参考官方文件,但尚未阅读更多解释