Skip to content

Commit

Permalink
#3173 - BeanSet lazy loading / Too many DataSource connections used
Browse files Browse the repository at this point in the history
- The error reported was that a DataSource connection pool maxed out
- The symptom was that there was an additional lazy loading queries invoked via the hashCode/equals implementation of ManyToMany Set.
- The fix is for BeanSet init() to lazy load with onlyIds = false, that avoids the extra lazy loading query from being executed
  • Loading branch information
rbygrave committed Aug 29, 2023
1 parent b7804e7 commit 359a55d
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 1 deletion.
2 changes: 1 addition & 1 deletion ebean-api/src/main/java/io/ebean/common/BeanSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ private void init() {
if (disableLazyLoad) {
set = new LinkedHashSet<>();
} else {
lazyLoadCollection(true);
lazyLoadCollection(false);
}
}
} finally {
Expand Down
38 changes: 38 additions & 0 deletions ebean-test/src/test/java/org/tests/sets/M2MDepart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.tests.sets;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import java.util.*;

@Entity
public class M2MDepart {

@Id
private UUID id;

private final String name;

@ManyToMany
private final Set<M2MEmp> employees = new LinkedHashSet<>();

public M2MDepart(String name) {
this.name = name;
}

public void addEmployee(M2MEmp employee) {
this.employees.add(employee);
}

public UUID getId() {
return id;
}

public String getName() {
return name;
}

public Set<M2MEmp> employees() {
return employees;
}
}
61 changes: 61 additions & 0 deletions ebean-test/src/test/java/org/tests/sets/M2MEmp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.tests.sets;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

@Entity
public class M2MEmp {

@Id
private UUID id;

private final String code;

private String name;

@ManyToMany
@JoinTable(name="m2m_dept_emp",
joinColumns=
@JoinColumn(name="employee_id", referencedColumnName="id"),
inverseJoinColumns=
@JoinColumn(name="department_id", referencedColumnName="id")
)
private final Set<M2MDepart> departments = new HashSet<>();

public M2MEmp(String name, String code) {
this.name = name;
this.code = code;
}

public UUID getId() {
return id;
}

public String getName() {
return name;
}

public String getCode() {
return code;
}

public Set<M2MDepart> getDepartments() {
return departments;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
M2MEmp employee = (M2MEmp) o;
return Objects.equals(code, employee.code);
}

@Override
public int hashCode() {
return Objects.hash(code);
}
}
31 changes: 31 additions & 0 deletions ebean-test/src/test/java/org/tests/sets/TestM2MSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.tests.sets;

import io.ebean.DB;
import io.ebean.test.LoggedSql;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class TestM2MSet {

@Test
void lazyLoadM2M_when_setWithHashCode_expect_selectProperties() {
final M2MDepart department = new M2MDepart("Test");
final M2MEmp employee = new M2MEmp("Test", "Code");
DB.save(employee);
department.addEmployee(employee);
DB.save(department);

LoggedSql.start();
DB.find(M2MDepart.class, department.getId())
.employees()
.forEach(e -> assertThat(e.getName()).isNotNull());

List<String> sql = LoggedSql.stop();
assertThat(sql).hasSize(2);
assertThat(sql.get(0)).contains("select t0.id, t0.name from m2_mdepart t0 where t0.id = ?");
assertThat(sql.get(1)).contains("select int_.m2_mdepart_id, t0.id, t0.code, t0.name from m2_memp t0 left join m2_mdepart_memp int_ on int_.m2_memp_id = t0.id where");
}
}

0 comments on commit 359a55d

Please sign in to comment.