Skip to content

@JoinColumns with @ManyToOne creates empty entity instead of null when no matching row #3664

@deverlex

Description

@deverlex

When using @ManyToOne with @JoinColumns in Ebean, if there is no matching row in the joined table, Ebean creates an empty entity instance (all fields null, id null) instead of setting the relation to null.

This behavior causes confusion and leads to NullPointerException when accessing properties of the empty entity.

@Entity
public class Transaction {
  @Id
  Long id;
  @Column(name = "org_id")
  Long orgId;

  @ManyToOne
  @JoinColumns({
    @JoinColumn(name = "org_id", referencedColumnName = "org_id", insertable = false, updatable = false),
    @JoinColumn(name = "order_id", referencedColumnName = "id")
  })
  Order order;
}

@Entity
public class Order {
  @Id
  Long id;

  @Column(name = "org_id")
  Long orgId;
}
// In DB: Transaction exists but has no matching Order (either FK null or no matching record)
Transaction tx = DB.find(Transaction.class).findOne();
System.out.println(tx.getOrder() != null); // true
System.out.println(tx.getOrder().getId()); // null

Expected behavior:
If there is no matching row for the join, tx.getOrder() should return null (similar to Hibernate's behavior when optional = true).

Actual behavior:
tx.getOrder() returns a non-null empty instance with all fields null. Developers have to check getId() != null instead of checking the reference itself, which is unintuitive and error-prone.

Impact:

Causes subtle bugs when developers assume null means no relation.

Leads to NullPointerException when accessing inner properties.

Breaks consistency with how Hibernate and other JPA providers behave.

Environment:
Ebean version: 15.11.0
Database: Mariadb 10.6
Java: 17

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions