JPA: связано несколько таблиц и используются условные запросы, но условие не работает - PullRequest
0 голосов
/ 09 июля 2019

Я хочу реализовать следующий SQL с помощью jpa:

    select u.id,u.name,u.address,o.title,o.description from user u
    left join orderd o
    where o.title='order1';

Но это не получилось так, как я хотел.

Я использую jbo-данные Springboot и spring data.

    //User Entity
    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        Integer id;

        String username;

        String addr;

        @JoinColumn(name = "userid", referencedColumnName = "id")
        @OneToMany(fetch = FetchType.EAGER)
        Set<Orderd> orderds;
    }

    //Orderd entity
    @Entity
    public class Orderd {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        Integer id;

        String title;

        String description;
    }



    @Test
        public void findByUserIdAndOrderdTitle() {
            Specification<User> userSpecification = new Specification<User>() {

                @Nullable
                @Override
                public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                    Join<User, Orderd> orderdJoin = root.join("orderds", JoinType.LEFT);

                    Predicate userIdEqual = criteriaBuilder.equal(root.get("id"), 1);
                    Predicate orderdTitleEqual = criteriaBuilder.equal(orderdJoin.get("title"), "apple");

                    criteriaQuery.where(userIdEqual, orderdTitleEqual);

                    return criteriaQuery.getRestriction();
                }
            };
            List<User> all = userRepository.findAll(userSpecification);

            for (User user : all) {
                System.out.println(user.getOrderds());
            }
    }

Я получаю значение:

    [Orderd {
        id = 2, title = 'apple', description = 'this is a apple'
    }, Orderd {
        id = 1, title = 'orange', description = 'this is a orange'
    }]

Но, я надеюсь, что это:

    [Orderd {
        id = 1, title = 'orange', description = 'this is a orange'
    }]

Я думаю, что я использовал фильтрацию идентификаторов для таблицы пользователя и заголовкафильтрация по таблице заказов, которая на самом деле является записью, но ее два.

Ниже приведен SQL для печати журналов:


    Hibernate: select user0_.id as id1_1_, user0_.addr as addr2_1_, user0_.username as username3_1_ from user user0_ left outer join orderd orderds1_ on user0_.id=orderds1_.userid where user0_.id=1 and orderds1_.title=?


    Hibernate: select orderds0_.userid as userid4_0_0_, orderds0_.id as id1_0_0_, orderds0_.id as id1_0_1_, orderds0_.description as descript2_0_1_, orderds0_.title as title3_0_1_ from orderd orderds0_ where orderds0_.userid=?

Очевидно, первый SQL удовлетворял моим потребностям, ноиз-за второго SQL результат оказался неверным.Я действительно надеюсь, что кто-то может мне помочь, большое спасибо!

1 Ответ

0 голосов
/ 09 июля 2019

Изменить оператор возврата вашей toPredicate функции внутри Specification<User> реализации:

return criteriaBuilder.and(userIdEqual, orderdTitleEqual); 

РЕДАКТИРОВАТЬ Если я правильно понимаю, вы хотите написать спецификацию для User whoимеет Orderd с конкретной Orderd.title в @OneToMany ассоциации, представленной User.orders, верно?

Если так, то ваша спецификация бессмысленна, потому что вы в основном спрашиваете, если User с конкретной id имеет и Order с конкретными title.Если вы хотите ВСЕХ пользователей, вы можете написать следующую спецификацию:

Specification<User> withOrderd(Orderd order) {
    return (root, query, builder) -> builder.isMember(order, root.get("orderds"));
}

Затем вы можете использовать это как:

Orderd order = ...; //pull order by title from database
List<User> users = userRepository.findAll(withOrderd(order));

В противном случае, вы можете сделать еще один Specification для ID:

Specification<User> withID(int id) {
    return (root, query, builder) ->  builder.equal(root.get("id"), id);
}

и используйте его:

Optional<User> user = userRepository.findOne(withOrderd(order).and(withID(id)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...