最近我问过一个关于Stack溢出的非常相似的问题,结果证明是另一个问题的副本。在另一个问题中,有一个解决方法我应用并解决了我的问题。现在,这次解决方法不起作用,并且所有其他提到的解决方案都不起作用。此外,链接到第一个线程的其他线程的所有解决方案都不起作用。
这是我最初的问题:
SQLServerException: Invalid column name
这就是重复:
我已经检查了链接和相关部分右侧的主题,但找不到我的问题的解决方案。我也无法理解我的问题发生的原因。
我有2个表:声明和文件(我不会在这里提及我的其他表格,因为它们与问题无关)
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和@OneToMany关系:
https://vladmihalcea.com/a-beginners-guide-to-jpa-and-hibernate-cascade-types/
我想要的是:删除声明,自动删除与声明相关的文件
我得到的结果:列名称'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启动
有没有人知道为什么这种情况发生,如果我知道为什么会发生这种情况我可能能够解决这个问题。现在我完全卡住了。
提前致谢。
修改
好的,所以偶然我解决了自己的问题,我仍然不知道为什么问题出现在第一位。根据这个主题的答案:
JPA JoinColumn vs mappedBy
你使用@ManyToOne&amp; @OnyToMany
在我的情况下,我不需要在File类中使用@ManyToOne。我在宣言课上只需要@OneToMany。删除此批注后不再出现错误。
如果有人知道这个问题的原因,请提供答案,以便将来可以为我或其他人使用。
答案 0 :(得分:0)
在我的情况下,我不需要在File类中使用@ManyToOne。我在宣言课上只需要@OneToMany。删除此批注后不再出现错误。
我不认为这会奏效。如果删除@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])
);
declaration_id
被声明为NOT NULL
,这意味着您无法在此表中保存任何内容,除非您在Declaration
表中为其指定了一个条目。这意味着您有两个选择:
您需要@ManyToOne
注释,以便JPA可以正确且自动地映射与您的数据库架构相对应的实体,或
从declaration_id
表中删除外键字段File
和相应的参照完整性约束。在这种情况下,持久性提供程序默认为您创建一个连接表,除非您自定义它。
因此,如果您想使用第一个选项,即@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
}
和略微修改的Declaration
实体:
@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.class
属性,因为您不需要它,因为您的集合已经暗示了该类型。