Repository: ebean-orm/ebean

Issue #2157: ManyToMany mapping to itself results in broken generated SQL DDL when not defining @JoinTable.
Created: 2021-02-10T13:06:45Z
Expected behavior
-- Something meaningful, similar to

create table countries_countries (
  country_1_id                  bigint generated by default as identity not null,
  country_2_id                  bigint generated by default as identity not null,
  constraint pk_countries_countries primary key (country_1_id,country_2_id)
);

create index ix_countries_countries_countries_1 on countries_countries (country_1_id);
alter table countries_countries add constraint fk_countries_countries_countries_1 foreign key (country_1_id) references countries (id) on delete restrict on update restrict;

create index ix_countries_countries_countries_2 on countries_countries (country_2_id);
alter table countries_countries add constraint fk_countries_countries_countries_2 foreign key (country_2_id) references countries (id) on delete restrict on update restrict;
Actual behavior
-- missing column for second country
create table countries_countries (
  countries_id                  bigint generated by default as identity not null,
  constraint pk_countries_countries primary key (countries_id)
);

-- foreign key created twice for same column
create index ix_countries_countries_countries_1 on countries_countries (countries_id);
alter table countries_countries add constraint fk_countries_countries_countries_1 foreign key (countries_id) references countries (id) on delete restrict on update restrict;

create index ix_countries_countries_countries_2 on countries_countries (countries_id);
alter table countries_countries add constraint fk_countries_countries_countries_2 foreign key (countries_id) references countries (id) on delete restrict on update restrict;

Steps to reproduce
@Entity
@Table(name = "countries")
public class CountryEbeanImpl implements Country {

  @ManyToMany(targetEntity = CountryEbeanImpl.class)
  // uncomment to see generated SQL DDL similar to above in expected behavior section
  // @JoinTable(name = "countries_countries",
  //      joinColumns = @JoinColumn(name = "country_1_id"),
  //      inverseJoinColumns = @JoinColumn(name = "country_2_id"))
  private Set<Country> allies;

}

Duplicate issue #2187: With @ManyToMany mapping seems does not take custom table and column names provided in @JoinTable 
Created: 2021-03-02T11:27:23Z
It is maybe related to #2186 but the issue that I got is when I try to override values auto-generated by ebean it seems it does not read the custom column names
So the question is: how I can customize the table name? I tried something like:
So if I have:
public class Student extends Model {

    @Id
    @Column(name = "StudentNumber", length = 35, nullable = false, updatable = false)
    private String studentNumber;

    // getters, and setters
}

public class Course extends Model {

    @Id
    @Column(name = "Id", nullable = false, updatable = false, unique = true)
    private UUID id;

   @ManyToMany(cascade = CascadeType.ALL)
    private List<Student> students;

    // getters, and setters
}
And in Course side I tried to do mapping like:
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "CustomCourseStudent",
            joinColumns = @JoinColumn(name = "CustomCourseId"),
            inverseJoinColumns = @JoinColumn(name = "CustomStudentNumber")
    )
    private List<Student> students;
or
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "CourseStudent",
            joinColumns = @JoinColumn(name = "CourseId"),
            inverseJoinColumns = @JoinColumn(name = "StudentNumber")
    )
    private List<Student> students;
Both didn't work, and it returns with error:
Caused by: javax.persistence.PersistenceException: Error with the Join on [models.Course.students]. Could not find the matching foreign key for [[Id]] in table[CourseStudent]? Perhaps using a @JoinColumn with the name/referencedColumnName attributes swapped?
	at io.ebeaninternal.server.deploy.BeanPropertyAssoc.findMatch(BeanPropertyAssoc.java:613)
	at io.ebeaninternal.server.deploy.BeanPropertyAssocMany.findMatch(BeanPropertyAssocMany.java:701)
	at io.ebeaninternal.server.deploy.BeanPropertyAssocMany.createExported(BeanPropertyAssocMany.java:689)
	at io.ebeaninternal.server.deploy.BeanPropertyAssocMany.initialiseAssocMany(BeanPropertyAssocMany.java:185)
	at io.ebeaninternal.server.deploy.BeanPropertyAssocMany.initialise(BeanPropertyAssocMany.java:153)
	at io.ebeaninternal.server.deploy.BeanDescriptor.initialiseOther(BeanDescriptor.java:636)
	at io.ebeaninternal.server.deploy.BeanDescriptorManager.initialiseAll(BeanDescriptorManager.java:525)
	at io.ebeaninternal.server.deploy.BeanDescriptorManager.deploy(BeanDescriptorManager.java:330)
	at io.ebeaninternal.server.core.InternalConfiguration.<init>(InternalConfiguration.java:177)
	at io.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:110)
	at io.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:35)
	at io.ebean.DatabaseFactory.createInternal(DatabaseFactory.java:123)
	at io.ebean.DatabaseFactory.create(DatabaseFactory.java:77)
	at play.db.ebean.orm.EbeanDynamicEvolutions.lambda$start$2(EbeanDynamicEvolutions.java:127)
	at java.base/java.util.HashMap.forEach(HashMap.java:1336)
	at play.db.ebean.orm.EbeanDynamicEvolutions.start(EbeanDynamicEvolutions.java:123)
	at play.db.ebean.orm.EbeanDynamicEvolutions.<init>(EbeanDynamicEvolutions.java:68)
	at play.db.ebean.orm.EbeanDynamicEvolutions$$FastClassByGuice$$9cd3c635.newInstance(<generated>)
The error mentions [Id] but it should be by default TableName_IdColumnName, the exception might get resolved in the other ticket, but still it seems when I tried to work around it, it does not read @JoinTable?

Closing comment (2021-03-02T19:52:42Z): Could not find the matching foreign key for [[Id]] in table[CourseStudent]

There is no [Id] specified in the @JoinColumn.  I think we need it explicitly via the referencedColumnName like:
  @ManyToMany(cascade = CascadeType.ALL)
  @JoinTable(
    name = "CourseStudent",
    joinColumns = @JoinColumn(name = "CourseId", referencedColumnName = "Id"),
    inverseJoinColumns = @JoinColumn(name = "StudentNumber", referencedColumnName = "StudentNumber")
  )

It is related to #2157?

I have not looked yet ...