0

I keep getting this error when I try to use multithreading (no problem if I run the program sequentially) in this service:

@Service
@RequiredArgsConstructor
public class Service {

    private final Repository repository;

    public List<A> getAs(String[] ids) {
        List<A> as = Collections.synchronizedList(new ArrayList<>());

        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        for (String id : ids) {
            futures.add(CompletableFuture.supplyAsync(() -> repository.findById(id).orElse(null)).thenApply(as::add));
        }

        futures.forEach(CompletableFuture::join);

        return as;
    }

}

Repository is a standard JpaRepository<A, String> and A:

public class A {

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

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "b")
    private B b;

}

The error is thrown when executing A#getB on any element of the returned list

2
  • 1
    Add @Transactional annotation above into your getAs method Commented Nov 28, 2022 at 11:52
  • @AnarMəmmədov already tried and it did not work Commented Nov 28, 2022 at 11:55

1 Answer 1

1

Because B is Lazy loaded.

  1. You can make this part in transaction and add init query:
repository.findById(id).map(v -> {v.getB(); return v;}).orElse(null))
  1. Or you can use create not lazy query:
public interface ARepository extends JpaRepository<A, String> { 
    @Query(value = "SELECT c FROM A c LEFT JOIN FETCH c.b where c.id = :id")   
    A findById(@Param("id") String id);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.