2 votes

Gestion JPA des valeurs nulles dans une requête construct avec selectcase

J'ai trois entités et une relation ternaire.

    public class User{}
    public class UserGroup{}
    public class Role{}
    public class User2Role2Group{
        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "USER_ID", nullable = false)
        private User user;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "ROLE_ID", nullable = false)
        private Role role;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "USER_GROUP_ID")
        private UserGroup group;
    }

Le groupe de User2Role2Group est nullable.

Il s'agit de mes données de test.

+----------+----------------+---------+---------+ | URG_ID | USER_GROUP_ID | USER_ID | ROLE_ID | +----------+----------------+---------+---------+ | urg_id1 | user_group_id1 | userId | roleID1 | | urg_id2 | user_group_id2 | userId | roleID1 | | urg_id3 | null | userId | roleID1 | | urg_id4 | user_group_id2 | userId | roleID2 | | urg_id5 | user_group_id1 | userId | roleID2 | +----------+----------------+---------+---------+

Je veux maintenant construire une liste d'objets de valeur "RoleGroup", qui contiennent les UserGroups et les Roles appartenant à un utilisateur.

Voici le code que j'ai écrit. Si le groupe n'est pas nul, je prends le groupe trouvé dans la base de données, sinon je construis un nullliteral pour le UserGroup.

    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery<RoleGroup> criteria = builder.createQuery(RoleGroup.class);
    final Root<User2Role2Group> from = criteria.from(User2Role2Group.class);
    criteria.select(builder.construct(RoleGroup.class, from.get(User2Role2Group_.role),
            builder.selectCase()
                    .when(builder.isNotNull(from.get(User2Role2Group_.group)), from.get(User2Role2Group_.group))
                    .otherwise(builder.nullLiteral(UserGroup.class))));
    criteria.where(builder.equal(from.get(User2Role2Group_.user).get(User_.userId), userId));
    final TypedQuery<RoleGroup> query = em.createQuery(criteria);
    return query.getResultList();

Le problème auquel je suis confronté est que lorsque le groupe est effectivement nul, comme dans mes données de test, je n'obtiens que quatre RoleGroups en retour.

Si j'intervertis les cas when et otherwise, j'obtiens même une SerializationException.

Ai-je mal compris selectCase ?

2voto

BetaRide Points 3311

Utilisation User2Role2Group_.group crée une jointure interne qui, par définition, n'est jointe que si l'élément USER_GROUP_ID contient une valeur non null valeur.

Ajoutez une jointure explicite à votre requête et marquez-la comme une jointure gauche pour obtenir null également. Je n'ai pas testé le code, mais quelque chose comme cela devrait vous permettre de démarrer.

Join<User2Role2Group, Group> join = from.join(User2Role2Group_.group, JoinType.LEFT);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X