4

I am attempting to create an entity which has a @OneToMany relationship with another entity. The problem I am having is when I use @JoinColumn(name = "QuizID") I get an error Cannot resolve column 'QuizID'.

As far as I understand the owning side needs a reference to the foreign key, being my Quiz.java, in particular it's id field. How do I reference this from @JoinColumn? How do I know what the column for id is called? I have tried id, quizid, Quiz_id, quizId etc etc.

Here is a snippet from the two @Entity classes with the problem

@Component
@Entity(name = "quiz_table")
public class Quiz {

    @Id
    private long id;

    @NotBlank(message = "Title must not be blank")
    private String title;

    @NotBlank(message = "Text must not be blank")
    private String text;

    @Size(min = 2)
    @NotNull
    @OneToMany(mappedBy = "quiz")
    private List<Options> options = new ArrayList<>();

    @JsonIgnore
    @OneToMany
    private List<Answer> answer = new ArrayList<>();

    public Quiz() {}

    // getters and setters ...
   
@Component
@Entity(name = "options_table")
public class Options {

    @Id
    @Column(name = "OptionsID")
    private long id;

    @ManyToOne
    @JoinColumn(name = "QuizID") // error here "Cannot resolve column"
    private Quiz quiz;

    private String option;

    public Options() {
    }

    // ... getters and setters

Here is an example from a tutorial I've been learning from that I'm struggling to understand. I am trying to understand the annotations for Spring and JPA, particularly @JoinColumn and @Column. In this example

@Entity
public class Tweet {
 
    @Id
    @Column(name = "TweetID")
    private long id;
 
    @ManyToOne
    @JoinColumn(name = "UserID")
    private User user;
}
@Entity
public class User {
 
    @Id
    private long id;
 
    @OneToMany(mappedBy = "user")
    private List<Tweet> tweets = new ArrayList<>();
 
}

How why is the @JoinColumn in Tweet class name attribute UserID? I understand it needs to be a column name from the User entity table (is that right?), but in entity User how do I know what the column names are? It just has a field for id, how does that become a column name UserID?

I have been looking at this SO post but when I follow the answer guide I don't have any options to "Assign data sources", it is the column beside entityManagerFactory is empty, or says "Missing data source".

My build.gradle

plugins {
    id 'org.springframework.boot' version '2.3.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
}

group = 'io.github.siaust'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {
    // New dependencies for a H2 database
//    implementation 'org.springframework.boot:sweb'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'com.h2database:h2'

    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation('org.springframework.boot:spring-boot-starter-validation')
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
    useJUnitPlatform()
}

The implementation 'org.springframework.boot:sweb' was from the tutorial but caused an error and I couldn't find any info on this dependency, others said it was "malformed", the H2 database loaded correctly and I could access it via localhost without this.

My application.properties

#datasource settings
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:file:../quizdb
spring.datasource.username=sa
spring.datasource.password=password

#data settings
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update

#console settings
spring.h2.console.enabled=true
spring.h2.console.settings.trace=false
spring.jpa.show-sql=true
#changes the path to the database in the browser, default is /h2-console
#spring.h2.console.path=/h2

As far as I can tell I'm using disk-based storage option for H2, not in-memory.

SimonA
  • 135
  • 2
  • 16
  • I am really struggling to understand what is being asked here. How do you know what the columns are called... in *your own* database schema? How did that schema came to be in the first place? – crizzis Jul 17 '20 at 13:11
  • 1
    The `@JoinColumn.name` is there *for you* to override the default column naming. If you don't care about the name, just don't specify it. Use a plain `@JoinColumn`. Also, if you tried multiple versions of the entity mappings, chances are the schema in the database file is no longer compatible with the current version (in which case - assuming you're only testing things out - just delete the `../quizdb` file and start from scratch) – crizzis Jul 17 '20 at 13:13
  • @crizzis My bad, I tried to include as much relevant info without making clear the issue. `@JoinColumn(name = "name")` had a warning under the name attribute in IntelliJ IDEA. I've since learned it doesn't prevent the code compiling or running, and have seen my database table column names reflect the changes in this annotation and `@Column`, `@Entity(name = "table_name")` etc. Yes I did end up with multiple unnecessary columns and deleted the database. Would there be a way to remove and update columns on such changes? – SimonA Jul 17 '20 at 19:16
  • 1
    The most reliable, production-ready way would be to externalize database schema change management to a tool like Flyway or Liquibase. You *could* use the JPA provider's schema update mode (if available), but it will [not always behave the way you'd expect](https://stackoverflow.com/questions/15978368/hibernate-hbm2ddl-auto-update-doesnt-update-column-definitions-in-mysql) – crizzis Jul 19 '20 at 16:06

0 Answers0