1

I have a hibernate code which was working well with the default join column value, but when I change the join column value to as desired by application convention it started breaking.
Before: @JoinColumn(name="state_name") List<City> cities;
After : @JoinColumn(name="state_nm") List<City> cities;

The problem is hibernate is creating the given column state_nm in the table but it is not using it. The table output is below.

mysql> select * from city;
+------------+------------+------------+----------+
| name       | population | state_name | state_nm |
+------------+------------+------------+----------+
| BayArea    | 7200000    | CA         | NULL     |
| Detriot    | 630000     | MI         | NULL     |
| LA         | 3900000    | CA         | NULL     |
| Miami      | 466000     | FL         | NULL     |
| RapidsCity | 188000     | MI         | NULL     |
+------------+------------+------------+----------+
5 rows in set (0.00 sec)

As you see, hibernate has still gone ahead and created the state_name column and as a result joins are returning null result.

2019-09-09 19:59:14.807 DEBUG 7812 --- [  restartedMain] org.hibernate.SQL                        : 
    create table city (
       name varchar(255) not null,
        population varchar(255),
        state_name varchar(255),
        state_nm varchar(255),
        primary key (name)
    ) engine=InnoDB
2019-09-09 19:59:16.158 DEBUG 7812 --- [  restartedMain] org.hibernate.SQL 

The Java Model Entities are below:

@Table(name="state")
@Entity
public class State { 

    @Id
    @Column(name="name")
    String name;
    @Column(name="population") 
    String population;  

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name="state_nm") 
    List<City> cities;

    @ManyToOne //(cascade=CascadeType.ALL, fetch=FetchType.EAGER) // don't use cascade all with ManyToOne, atleast for now
    Country country; 
    getters/setters

@Table(name="city")
@Entity
public class City {

        @Id
        @Column(name="name")
        String name;

        @Column(name="population")
        String population;

        @ManyToOne 
        State state;
        getters/setters

Any hint's on why this behavior.

code can be found on branch "joincolumn_issue": https://github.com/samshers/graphql-hibernate/tree/joincolumn_issue

Edit: This question is different. In the first place it is not about @Column or @JoinColumn, it is about being able to give a user defined name to the @JoinColumn. Hibernate provides three ways of doing OneToMany Mapping. The approach posted in this question can be considered as one way. The answer from @Sterconium can be seen as second approach where mappedBy is used. Next there is a @JoinTable based approach. So, Here I am looking for solution based on first approach where I can define a join column name as per application demand. So this question is no way related to the other question.

samshers
  • 1
  • 6
  • 37
  • 84
  • @Moderator, please unmark this question as duplicate or "might be answered here" as this is entirely different approach from the other. – samshers Sep 09 '19 at 21:32

1 Answers1

1

Try with the following:

On class State, replace

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="state_nm") 
List<City> cities;

with

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy = "state")
List<City> cities;

On class City, replace

@ManyToOne 
State state;

With

@ManyToOne
@JoinColumn(name="state_nm")
State state;

Which I guess can be summarized in

  • Define the relationship on City instead of State (not sure about the terminology, I'm new to hibernate);
  • Use @JoinColumn instead of @Column

By doing so the create city query logged becomes:

2019-09-09 17:49:37.821 DEBUG 3180 --- [  restartedMain] org.hibernate.SQL                        : 

    create table city (
       name varchar(255) not null,
        population varchar(255),
        state_nm varchar(255),
        primary key (name)
    ) engine=InnoDB

And the constrain logged is:

2019-09-09 17:49:39.033 DEBUG 3180 --- [  restartedMain] org.hibernate.SQL                        : 

    alter table city 
       add constraint FKnpj8mmul6j6kcl7p90bdo1gj7 
       foreign key (state_nm) 
       references state (name)

I referred to this tutorial and this question

Hope I helped

Sterconium
  • 559
  • 4
  • 20
  • your solution is right and work's. It's based on using `mappedBy` . Hibernate provides three ways of doing OneToMany Mapping. The approach posted in this question can be considered as first way. The answer from @Sterconium (you) can be seen as second approach where mappedBy is used. Next there is a @JoinTable based approach. So, Here I am looking for solution based on first approach where I can define a join column name as per application demand. Tying to explore the 3 approaches, so I can understand if there is any limitation defined by hibernate, so I know when to use which. – samshers Sep 09 '19 at 21:08
  • moving my code to use mappedBy as this seems to works in consistent manner than other approaches. +1, – samshers Sep 14 '19 at 06:30