JPA / Hibernate: Les relations @ManyToOne et @OneToOne marquées comme FetchType.LAZY et optional = false ne se téléchargent pas paresseusement sur em.find ()?

J'ai l'entité ci-dessous (uniquement les mappages):

@Entity
@Table(name = "PQs")
public class PQ implements Serializable
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Integer id;

    @Column
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)                 //lazy XToOne
    @JoinColumn(name = "user_id", referencedColumnName = "person_id")
    private User user;

    @OneToOne(mappedBy = "pq", fetch = FetchType.LAZY) //lazy XToOne
    private Group group;

    @OneToOne(mappedBy = "pq", fetch = FetchType.LAZY) //lazy XToOne
    private Tendering tendering;

    ...
}

Noter les commentaires ci-dessus: il y a trois @XToOne relations avec d'autres entités:

Utilisateur (un SecurityIdentity sous-classe avec un simple ID PK, référencé par PQ, représentant le propriétaire):

@Entity
@Table(name = "Users")
@DiscriminatorValue(value = "user")
public class User extends SecurityIdentity
{
    @Column
    private String name;

    @OneToMany(mappedBy = "user")
    private Set<PQ> pqs = new HashSet<PQ>();

    ...
}

Groupe (également un SecurityIdentity sous-classe avec un simple ID PK, les références, le PQ afin de représenter un ensemble d'utilisateurs qui peuvent interagir avec le PQ):

@Entity
@Table(name = "Groups")
@DiscriminatorValue(value = "group")
public class Group extends SecurityIdentity
{
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "pq_id", referencedColumnName = "id")
    private PQ pq;

    ...
}

D'appel d'offres:

@Entity
@Table(name = "Tenderings")
public class Tendering implements Serializable
{
    @Id
    @Column(name = "pq_id", insertable = false, updatable = false)
    private Integer pqId;

    @Column(name = "external_code")
    private String externalCode;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "pq_id", referencedColumnName = "id")
    private PQ pq;

    ...
}

Ne pas être confus au sujet d'utilisateurs et de groupes de partage de l'IDs, juste de les traiter comme de simples Identifiants. Un appel d'offres est juste un document distinct de l'objet (un-à-un).

Comme vous pouvez le voir il y a trois @XToOne relations sur le PQ entité, qui, si aucun type d'extraction a été fixé, serait chargé avec impatience la JPA (par défaut). Donc, pour éviter cela j'ai marqué tous les @XToOne relations FetchType.LAZY.

Maintenant lors de l'utilisation de

em.find(PQ.class, someExistingId);

- Je obtenir de l'Hibernation de sortie:

23:53:55,815 INFO  [stdout] Hibernate: select pq0_.id as id291_0_, pq0_.description as descript2_291_0_, pq0_.name as name291_0_, pq0_.submission_date as submission4_291_0_, pq0_.user_id as user5_291_0_ from PQs pq0_ where pq0_.id=?
23:53:55,818 INFO  [stdout] Hibernate: select user0_.id as id280_0_, user0_1_.identity_type_id as identity2_280_0_, user0_.is_enabled as is1_297_0_, user0_.name as name297_0_, user0_.password as password297_0_, user0_.person_id as person5_297_0_ from Users user0_ inner join SecurityIdentities user0_1_ on user0_.id=user0_1_.id where user0_.person_id=?
23:53:55,821 INFO  [stdout] Hibernate: select group0_.id as id280_0_, group0_1_.identity_type_id as identity2_280_0_, group0_.pq_id as pq2_281_0_ from Groups group0_ inner join SecurityIdentities group0_1_ on group0_.id=group0_1_.id where group0_.pq_id=?
23:53:55,823 INFO  [stdout] Hibernate: select tendering0_.pq_id as pq1_296_0_, tendering0_.binary_file as binary2_296_0_, tendering0_.customer_id as customer6_296_0_, tendering0_.description as descript3_296_0_, tendering0_.external_code as external4_296_0_, tendering0_.title as title296_0_ from Tenderings tendering0_ where tendering0_.pq_id=?

Les trois Sélectionne les souches de l' @XToOne relations (comme décrit dans de nombreux endroits sur le net). La source que j'étais en train de regarder la plupart du temps est ceci:

Faire un OneToOne-rapport paresseux

Comme mentionné, le @ManyToOne relation User user ne devrait pas être récupérés:

@ManyToOne(fetch=FetchType.LAZY) devrait fonctionner parfaitement.

... ici la relation de PQ à Utilisateurmais il est extraites comme vous pouvez le voir sur la select user0_.id as id280_0_, ... déclaration...

Pour les deux autres Group group et Tendering tenderingà la fois @OneToOne inverse mappages, les clés étrangères de référence de la PQs de la table de PK (ID), ce qui entraîne le même mappage dans le PQ entité.

À noter que les trois relations ne sont pas en option: un PQ a toujours un propriétaire (utilisateur), et un PQ est toujours référencé par un appel d'offres et d'une entité du groupe. Je n'avais simplement pas modélisé que dans JPA-dessus encore...

Donc, lors de l'ajout d' optional = false pour les trois relations du PQ entité:

@Entity
@Table(name = "PQs")
public class PQ implements Serializable
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Integer id;

    @Column
    private String name;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id", referencedColumnName = "person_id")
    private User user;

    @OneToOne(mappedBy = "pq", fetch = FetchType.LAZY, optional = false)
    private Group group;

    @OneToOne(mappedBy = "pq", fetch = FetchType.LAZY, optional = false)
    private Tendering tendering;

    ...
}

... J'ai le Hibernate sortie:

00:47:34,397 INFO  [stdout] Hibernate: select pq0_.id as id361_0_, pq0_.description as descript2_361_0_, pq0_.name as name361_0_, pq0_.submission_date as submission4_361_0_, pq0_.user_id as user5_361_0_ from PQs pq0_ where pq0_.id=?
00:47:34,410 INFO  [stdout] Hibernate: select user0_.id as id350_0_, user0_1_.identity_type_id as identity2_350_0_, user0_.is_enabled as is1_367_0_, user0_.name as name367_0_, user0_.password as password367_0_, user0_.person_id as person5_367_0_ from Users user0_ inner join SecurityIdentities user0_1_ on user0_.id=user0_1_.id where user0_.person_id=?
00:47:34,413 INFO  [stdout] Hibernate: select group0_.id as id350_0_, group0_1_.identity_type_id as identity2_350_0_, group0_.pq_id as pq2_351_0_ from Groups group0_ inner join SecurityIdentities group0_1_ on group0_.id=group0_1_.id where group0_.pq_id=?

Note, que je n'ai été jouer avec le optional = false sur le PQ entité, car c'est celui que j'utilise dans em.find(...). (Si ce n'est pas suffisant, veuillez m'éclairer.)

Ma question maintenant est de deux ordres:

  1. Pourquoi le @ManyToOne à la User entité extraite avec impatience (étant donné que c'était, dit-on travailler paresseusement, voir Faire un OneToOne-rapport paresseux)?
  2. Pourquoi n'est que le OneToOne relation à la Tendering entité laissé être récupérées? Est-ce parce que la Tendering les références d'entité du PQ PK colonne de PK elle-même (@Id dans Tendering), qui le Group entité n'a pas (relation régulière au PQ, PK)?

Quel est le problème? Comment puis-je faire de ces non-facultatif relations paresseux? (sans code d'instrumentation ou d'autres hacks, tout simplement annotations...)

Je sais que le PARESSEUX chose, c'est juste un conseil pour le fournisseur JPA de faire quelque chose à propos de chargement paresseux ou pas, mais dans ce cas, il semble que si quelque chose est mauvais (il fonctionne).

PS: je suis en utilisant Hibernate 4.0 BÊTA, la version qui vient avec JBoss 7.0.0.Final avec les annotations JPA seulement (le ci-dessus sont tous JPA 1.0 compatible).

source d'informationauteur Kawu