0

Recently I have asked a very similar question on Stack overflow which turned out to be a duplicate of another question. In that other question there was a workaround which I applied and solved my problem. Now, this time the workaround doesn't work, and all other mentioned solutions don't work. Also all the solutions from other threads linked to the first thread don't work.

This was my question at first:

SQLServerException: Invalid column name

And this was the duplication:

hibernate column name issues

I have checked the topics on the right in the Linked and Related sections but can't find an solution to my problem. I also cannot comprehend the reason why my problem occurs.

I have 2 tables: Declaration and File (I won't mention my other tables here because they are irrelevant to the problem)

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])
    );

With the corresponding classes:

@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;
    }
}

And

@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;
    }
}

I have defined my @ManyToOne and @OneToMany relations based on these topics and tutorials:

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

JPA JoinColumn vs mappedBy

What I want: Delete Declaration, automatically delete files related to the declaration

What I get: Invalid column name 'declaration_id_number'.

What I have tried:

- 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

The actual SQL query:

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=?

I am running Spring boot with JPA Hibernate 5.2.10

Is there anyone out there who knows why this happends, if I know why it happends I might be able to fix the problem my self. Right now I am completely stuck.

Thanks in advance.

EDIT:

Ok, so by accident I solved my own problem, I still don't know why the problem occured in the first place. According to this answer(s) of this topic:

JPA JoinColumn vs mappedBy

You use @ManyToOne & @OnyToMany

In my case I don't need to use @ManyToOne in the File class. I only need @OneToMany in my Declaration class. No more errors occur after I removed this annotation.

If anyone knows the reason for this problem, please provide an answer so that it can be of use in the future for me or someone else.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
Niek Jonkman
  • 1,014
  • 2
  • 13
  • 31
  • Your question is rather jumbled. It's not clear just what code you ran. Tell us what you did exactly to "get: Invalid column name 'declaration_id_number'". Why is your query two queries? Also, they aren't queries, they are templates. Also, it's not clear how we are suposed to make sense of your list of "What I have tried", ie what code you would have run for each one, & why the last three lines are there. Please read & act on [mcve]. – philipxy Oct 19 '17 at 10:23

1 Answers1

0

In my case I don't need to use @ManyToOne in the File class. I only need @OneToMany in my Declaration class. No more errors occur after I removed this annotation.

I don't think that this will work. If you remove the @ManyToOne annotation, the persistence provider will create a join table by default to maintain the relationship. What you mean is probably that you don't get any exception. But look at the database schema:

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 is declaraed to be NOT NULL which means you cannot save anything in this table unless you assign it an entry in the Declaration table.
  • You have defined a foreign key constraint which means your database will check this when you save a file record.

This means that you have two options:

  • you need an @ManyToOne annotation so that JPA can map the entities correctly and automatically that will correspond to your database schema, or

  • you remove the foreign key field declaration_id and the corresponding referential integrity constraint from the File table. In this case, the persistence provider will create a join table by default for you, unless you customize it.

So if you want to use the first option, i.e. @ManyToOne annotation, you have to map the entities as follows:

@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
}

and a slightly modified Declaration entity:

@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
}

Notes:

  • I removed targetEntity = File.class attribute from the annotation because you don't need it as your collection already implies the type.
  • Why are you putting table/column names into the square brackets? They make the code unreadable and I don't see the benefit of using it.
ujulu
  • 3,289
  • 2
  • 11
  • 14