question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SQL for Index and Foreign Key didn't get generated if I map ID column after @ManyToOne

See original GitHub issue

This issue is kinda strange with an easy workaround to fix it, I’m not sure if that’s an issue though, so the idea is if I have Model that maps another Model and used @JoinColumn to do that mapping (I’m not sure if this is part of issue actually), the SQL script that should be generated only appears if and only if mapping the id column is BEFORE the mapping it with @ManyToOne

I mean this is confusing but here is an example:

Steps to reproduce

If I have UserSubscriptions bean, that bean got Topic, like the following:

@Entity
@Table(name = "UserSubscription", schema = "alerts")
public class UserSubscription extends Model {
    @ManyToOne(optional = false, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @DbForeignKey(onDelete = ConstraintMode.CASCADE)
    @JoinColumn(name = "TopicId")
    private Topic topic;

    @Column(name = "TopicId", nullable = false, insertable = false, updatable = false)
    private Integer topicId;

SQL should generate:

create index [ix_UserSubscription_TopicId] on [alerts].[UserSubscription] ([TopicId]);
alter table [alerts].[UserSubscription] add constraint [fk_UserSubscription_TopicId] foreign key ([TopicId]) references [alerts].[Topic] ([Id]) on delete cascade;

But in this case, here it is not working, I have to maintain the order between properties so I have to change my code to:

@Entity
@Table(name = "UserSubscription", schema = "alerts")
public class UserSubscription extends Model {

    @Column(name = "TopicId", nullable = false, insertable = false, updatable = false)
    private Integer topicId;

    @ManyToOne(optional = false, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @DbForeignKey(onDelete = ConstraintMode.CASCADE)
    @JoinColumn(name = "TopicId")
    private Topic topic;

In this case, the SQL script showing up.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
jnehlmeiercommented, Nov 16, 2021

In JPA/EclipseLink I used something like that before. Using the above classes as example I think it was along the lines of having a larger list of UserSubscription instances and instead of triggering lazy load by calling getTopic() I collected topicIds and did a query manually. This was a last resort solution to avoid lots of lazy load queries when JOIN FETCH and BATCH FETCH both did not work properly in JPA/EclipseLink.

Sometimes I also used it to optimize a query since EclipseLink usually uses the pattern JOIN subscription.topic t WHERE t.id = :id instead of just WHERE subscription.topicId = :id. So it favors adding a JOIN and comparing the primary key column instead of comparing the foreign key column directly. That extra JOIN sometimes caused slow query plans in the DB.

So it is mainly used as a workaround for other issues.

0reactions
rbygravecommented, Feb 2, 2022

Pushed a fix, again noting that really people shouldn’t need to map the same column twice.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The best way to map a @OneToMany relationship with JPA ...
The @ManyToOne annotation allows you to map the Foreign Key column in the child entity mapping so that the child has an entity...
Read more >
java - Mapping a @OneToMany relation with a primary key as ...
As it can be seen, the "activity_property" table uses a composite primary key with (id,name) and column "id" being a foreign key to...
Read more >
How to Index Foreign Key Columns in SQL Server
In this blog post we will show you step by step how to Index Foreign Key Columns in SQL Server and will show...
Read more >
ManyToOne with foreign keys on distinct tables - EclipseLink
You can resolve this in your customizer by remove the 2nd foreign key, DatabaseField country = new DatabaseField("COUNTRY"); mapping.
Read more >
Chapter 2. Mapping Entities - Red Hat on GitHub
The other mapping declarations are implicit. The class Flight is mapped to the Flight table, using the column id as its primary key...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found