Значение результата изменяется при добавлении соединения с другой таблицей - PullRequest
0 голосов
/ 02 мая 2020

У меня есть приложение Spring Boot, которое взаимодействует с базой данных MySql через Hibernate. Приложение управляет расходами, выполняемыми пользователями.
Проблема в том, что, если я отфильтрую расходы по имени пользователя, значение логического столбца изменится в результатах, в то время как без этого условия условие будет правильным. В главе Проблема Я более подробно объясняю это странное поведение, которое я нашел, и спрашиваю объяснения.

Информация о модели

У расхода есть один автор.
У расхода есть положительное значение в поле amount, которое представляет денежные средства, в то время как is_income сообщает, является ли расход доходом или нет.

Контекст весенней загрузки

Как я писал в Во вступлении я использую Spring Boot и Hibernate для взаимодействия с базой данных. В частности, я использую Criteria API для написания запросов, потому что мне нужно строить запросы динамически на основе пользовательских запросов.

CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Expense> criteriaQuery = builder.createQuery(Expense.class);
Root<Expense> root = criteriaQuery.from(Expense.class);
root.alias("entity");

// author predicate
Predicate authorPredicate = builder.equal(root.get("author").<String>get("username"), username);
Predicate filterPredicates = criteriaQueryHelper.getFilterPredicates(builder, root, params);

Predicate bothPredicates = builder.and(filterPredicates, authorPredicate);
criteriaQuery.where(bothPredicates);
List<Expense> expenses = entityManager.createQuery(criteriaQuery)
                .setFirstResult(page * pageSize)
                .setMaxResults(pageSize)
                .getResultList();

, где getFilterPredicates() позволяет извлечь условие для поля is_income и authorPredicate является причиной, которая вызывает проблему в некотором роде, которую я не могу понять.

Проблема

Если я запрашиваю базу данных для расходов с суммой больше 1, которые являются результат (is_income = false) выполняется следующий запрос:

select expense0_.expense_id as expense_1_0_, expense0_.amount as amount2_0_, expense0_.username as username8_0_, 
expense0_.billing_date as billing_3_0_, expense0_.description as descript4_0_, expense0_.is_income as is_incom5_0_, 
expense0_.insertion_date as insertio6_0_, expense0_.market_id as market_i9_0_, expense0_.title as title7_0_ 
from expense expense0_ 
where expense0_.amount>1.0 and expense0_.is_income=false
order by expense0_.amount desc limit 10;

, и я ожидаю результатов:

expense_1_0_,amount2_0_,username8_0_,billing_3_0_,descript4_0_,is_incom5_0_,insertio6_0_,market_i9_0_,title7_0_
38,          150,3,"2020-04-19 22:00:00",NULL,                 0,          "2020-04-25 13:25:52",NULL,Televisore
35,          35,3,"2020-04-18 22:00:00",NULL,                  0,          "2020-04-25 13:24:19",NULL,Spesa
34,          30,3,"2020-02-19 23:00:00",NULL,                  0,          "2020-04-25 13:23:58",NULL,Benzina
58,          26,5,"2020-04-23 22:00:00",NULL,                  0,          "2020-05-01 22:15:40",NULL,"Spesa senza prodotti"
57,          25,5,"2020-05-10 22:00:00",NULL,                  0,          "2020-05-01 22:14:42",NULL,Normale
55,          14.5,5,"2020-04-30 20:00:00",,                    0,          "2020-04-29 19:40:29",NULL,"Spesa settimanale"
54,          14.5,5,"2020-04-29 19:33:49",,                    0,          "2020-04-29 19:34:24",NULL,"Spesa settimanale"
45,          14.5,5,"2020-04-27 06:30:25",,                    0,          "2020-04-27 06:30:25",NULL,"Spesa settimanale"
46,          14.5,5,"2020-04-27 06:32:49",,                    0,          "2020-04-27 06:32:49",NULL,"Spesa settimanale"
33,          12,3,"2020-03-24 23:00:00",NULL,                  0,          "2020-04-25 13:23:34",NULL,"Disney Plus"

Пожалуйста, обратитесь к столбцу is_incom5_0_ в результате, который соответствует столбцу is_income базы данных и столбцу expense_1_0_, который является expense_id.
Когда я добавляю условие для указанного c пользователя:

select expense0_.expense_id as expense_1_0_, expense0_.amount as amount2_0_, expense0_.username as username8_0_, 
expense0_.billing_date as billing_3_0_, expense0_.description as descript4_0_, expense0_.is_income as is_incom5_0_, 
expense0_.insertion_date as insertio6_0_, expense0_.market_id as market_i9_0_, expense0_.title as title7_0_ 
from expense expense0_ 
cross join user user1_ 
where expense0_.username=user1_.id and expense0_.amount>1.0 and expense0_.is_income=false and user1_.username='mruser'
order by expense0_.amount desc limit 10;

значение поля is_income изменяется с 0 на 1 . Посмотрите, например, на расходы с идентификатором 58.

expense_1_0_,amount2_0_,username8_0_,billing_3_0_,descript4_0_,is_incom5_0_,insertio6_0_,market_i9_0_,title7_0_
58,          26,5,"2020-04-23 22:00:00",NULL,                  1,          "2020-05-01 22:15:40",NULL,"Spesa senza prodotti"
57,          25,5,"2020-05-10 22:00:00",NULL,                  1,          "2020-05-01 22:14:42",NULL,Normale
45,          14.5,5,"2020-04-27 06:30:25",,                    1,          "2020-04-27 06:30:25",NULL,"Spesa settimanale"
46,          14.5,5,"2020-04-27 06:32:49",,                    1,          "2020-04-27 06:32:49",NULL,"Spesa settimanale"
54,          14.5,5,"2020-04-29 19:33:49",,                    1,          "2020-04-29 19:34:24",NULL,"Spesa settimanale"
55,          14.5,5,"2020-04-30 20:00:00",,                    1,          "2020-04-29 19:40:29",NULL,"Spesa settimanale"
50,          10,5,"2020-04-26 22:00:00",NULL,                  1,          "2020-04-28 21:41:49",NULL,Prova
51,          10,5,"2020-04-27 22:00:00",NULL,                  1,          "2020-04-29 06:04:59",NULL,"Spesa con prodotto"
41,          10,5,"2020-04-26 22:00:00",NULL,                  1,          "2020-04-26 16:39:30",NULL,"Spesa di prova"
40,          4.25,5,"2020-04-25 13:39:41","",                  1,          "2020-04-25 13:39:42",NULL,Grigliata

Я запускаю оба запроса непосредственно в базе данных, и результат совпадает.
Мне интересно Как возможно это добавить a условие условия изменяет значение столбца с тем же идентификатором?

Модель гибернации

Класс расходов

@Data
@Table(name= Constants.MySql.Tables.Expense.TABLE_NAME)
public class Expense {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name= Constants.MySql.Tables.Expense.ID)
    private long id;

    @Column(name=Constants.MySql.Tables.Expense.AMOUNT)
    private Float amount;

    @Column(name=Constants.MySql.Tables.Expense.TITLE)
    private String title;

    @Column(name=Constants.MySql.Tables.Expense.DESCRIPTION)
    private String description;

    @Column(name=Constants.MySql.Tables.Expense.BILLING_DATE)
    private Date billingDate;

    @Column(name=Constants.MySql.Tables.Expense.INSERTION_DATE)
    private Date insertDate;


    @Column(name=Constants.MySql.Tables.Expense.IS_INCOME)
    private Boolean income;


    @ManyToOne
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JoinColumn(name=Constants.MySql.Tables.User.ID)
    @JsonIgnoreProperties("")
    private User author;

}

Класс пользователя

@Entity
@Table
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = Constants.MySql.Tables.User.ID, unique = true)
    private String username;

    @Column(name = Constants.MySql.Tables.User.NAME)
    private String name;

    @Column(name = Constants.MySql.Tables.User.SURNAME)
    private String surname;

    @Column(unique = true)
    private String email;

    @Column
    @JsonIgnore
    private String password;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "user_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles = new HashSet<>();

}
...