Двустороннее соединение в JPA Criteria Building - PullRequest
0 голосов
/ 04 марта 2020

У меня есть три сущности, например: -

@Entity
@Table(name = "product")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    @Expose
    private long id;

    @ManyToOne
    @JoinColumn(name = "users_id")
    @Expose
    private User user;
}

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    @Expose
    private long id;
}


@Entity
@Table(name = "users_phone")
public class UserPhone {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    @Expose
    private int id;

    @ManyToOne
    @JoinColumn(name = "users_id")
    @Expose
    private User user;
}

Теперь я хочу получить результаты из таблицы продуктов, основанной на объединении трех таблиц. Поэтому я сделал Спецификацию, чтобы я мог передать ее в хранилище. Вот код для спецификации.

    Specification<ProductPost> productSpecification = new Specification<ProductPost>() {
        @Override
        public Predicate toPredicate(Root<ProductPost> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
            List<Predicate> predicates = new ArrayList<>();
            criteriaQuery = criteriaBuilder.createQuery();

            if (userName.length() > 0) {
                predicates.add(criteriaBuilder.like(root.join("user").<String>get("fullName"), "%" + userName + "%"));
            }
            if (phoneNumber.length() > 0) {
                // Below line isn't working actually as  join("UserPhone") - 'user' table has no reference for 'userPhone'. But 'userPhone' has 'user'.
                predicates.add(criteriaBuilder.like(root.join("user").join("UserPhone").<String>get("phoneNumber"), "%" + postType + "%"));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        }
    };

Да, будет легко, если у меня будет ссылка 'userPhone' в таблице 'user', например - product -> user -> userPhone вместо product -> user, userPhone -> user. Но моя схема такая. Теперь я сталкиваюсь с проблемами при объединении трех таблиц и получении результатов.

1 Ответ

0 голосов
/ 04 марта 2020

Если вместо join присвоено cross-join, вы можете попробовать это решение

if (phoneNumber.length() > 0) {
    Root<UserPhone> userPhone = query.from(UserPhone.class);

    predicates.add(criteriaBuilder.equal(
        root.join("user").get("id"), 
        userPhone.get("user").get("id")
    ));

    predicates.add(criteriaBuilder.like(
        userPhone.get("phoneNumber"), 
        "%" + postType + "%"
    ));
}
...