https://kotlinlang.org logo
Title
m

Marcus Dunn

02/08/2021, 11:24 PM
Hello is there a proper way to map JPA's
FetchType.LAZY
to a schema-exposed class? If I pass a entity to the constructor then just call the field inside the function (example below) I'll receive an error because the session is closed by the time the function is called. I have this entity class
@Entity
class Foo(
    @Id
    val id: Long
    @OneToOne(fetch = FetchType.LAZY)
    var bar: Bar
)
this class here is the one exposed to the schema, its mapped almost 1-1 with the
Foo
class, but with the potential to have more fields I don't necessarily want in the
Foo
entity.
class GraphQlFoo(private val entity: Foo) {
    val id = entity.id
    fun bar() = GraphQLBar(entity.bar)
}
This setup breaks at the moment, Ideally I'd like some way to fetch
bar
if and only if it was requested, and not have to do unessisary joins if it the request doesn't include it. I'd also like to do all this logic in a single session, as opening a second to just fetch
bar
seems unneeded which is what my current solution does via
fun bar(@GraphQLIgnore @Autowired barRepository: BarRepository) = barRepository.getByFooId(id)
s

Shane Myrick

02/09/2021, 12:02 AM
The
GraphQLFoo.bar()
function only runs when the client has the
bar
field in their query. I am not too familiar with JPA, but if the entity is already constructed and executed before hand then, yes, you are going to still be running the code even if no client even selects
foo
. The approach you mentioned by using the
barRepository
would be my recommended way but you can also achieve that with the constructor params
class GraphQlFoo (
  private val entity: Foo,
  private val barRepository: BarRepository
) {
    val id = entity.id
    fun bar() = barRepository.getByFooId(entity.id)
}
m

Marcus Dunn

02/09/2021, 12:07 AM
yes that part works great at the moment: requests that dont ask for
bar
have no extra overhead. The issue is (and perhaps I'm over-engineering this) is that
barRepository.getByFooId(entity.id)
opens up a second session (the first one being the original query for
Foo
) and doesn't use the fact I've got the foreign key for
Bar
in the
Foo
entity already (albeit without the join having occurred yet).