When executing a jpql query FetchMode.JOIN (which is the default for eager to one relations) is ignored. This is reasonable, because it would alter the query executed by the user. The unfortunate side effect is that n+1 queries are executed to fill the eager relation. Making the relation lazy is not always possible, because a non-owning optional relation can't be lazy.
To prevent n+1 queries you can use the awesome feature @BatchSize or hibernate.default_batch_fetch_size. This works fine for both lazy and eager one-to-one relations on the owning side, but it does not work for non-owning eager (lazy is not possible due to ) one-to-one relations.
This is a big performance problem and I believe this is the main reason why people say one should avoid bidirectional one-to-one relations in hibernate.
Looking at the code this is because in EntityType.resolve it uses loadByUniqueKey for non-owning one-to-one realations, but unlike resolveIdentifier which internally calls DefaultLoadEventListener.loadFromDatasource which uses batch fetching, loadByUniqueKey uses Loader.doQuery which does not use batch fetching.