Hibernate createNativeQuery возвращает повторяющиеся строки - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть 2 таблицы базы данных Клиент и Элементы с отношением 1 -> много. Для получения данных из базы данных я использую следующий запрос.

выберите customer.id, customer.name, items.itemName, items.itemPrice из testdb.customer. ВНУТРЕННИЕ СОЕДИНЕНИЯ

У меня есть сущность класса Customers

@Entity    
public class Customer{

@Id
private int id;

@Column
private String name;

@Column
private String itemName;

@Column
private int itemPrice;

public Customer() {}
 //Getter and setter are here
.......
}

в классе обслуживания у меня следующий код.

@GET @Path("/getCustomerInfo")
@Produces(MediaType.APPLICATION_JSON)
public List getCustomerInfo() {
    CustomerDao dao = new CustomerDao();
    return dao.getBuildingsCustomerInfo();
}

в моем классе DAO у меня есть следующий код

public List<Customer> getCustomerInfo(){
    Session session = SessionUtil.getSession();
    String queryString = "the above mentioned query";
    List<Customer> customerInfo = session.createNativeQuery(queryString, Customer.class) ;
    session.close();
    return customerInfo;
}

Я получаю следующий ответ JSON от службы

[id:1, name:"Alfred", itemName:"jeans", itemprice:10],[id:1, name:"Alfred", itemName:"jeans", itemprice:10],[id:2, name:"James", itemName:"watch", itemPrice:20 ],[id:2, name:"James", itemName:"watch", itemPrice:20 ], [id:2, name:"James", itemName:"watch", itemPrice:20 ]

Количество результатов равно 5, что является правильным, но 2-й результат - это копия 1-го, 4-го и 5-го - копии 3-го. Во 2-м, 4-м и 5-м результатах itemName и itemPrice должны быть разными.

если я использую createSQLQuery(queryString); вместо createNativeQuery(queryString, Customer.class);, я получаю правильный результат, но без имен атрибутов сущностей.

[1, "Alfred", "jeans", 10],[1, "Alfred", "shirt", 15],[2, "James", "watch", 20], [2, "James", "coffee", 25], [2, "James", "drinks", 30]

Я видел несколько статей, но не смог найти решение. Я должен использовать createNativeQuery (), а не createSQLQuery (), потому что мне нужно сопоставить атрибуты класса сущности. Пожалуйста, дайте мне знать, если я делаю что-то не так.

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Ваша структура данных неверна на стороне Java и не соответствует отношению к базе данных. В отношении, которое вы описываете, у вас должен быть список предметов:

@Entity    
public class Customer implements Serializable {
    // ... the fields you have so far

    // assuming the parent field on the other side is called customer
    // you may also want to set the cascade and orphanRemoval properties of the annotation
    @OneToMany(mappedBy = "customer")
    @JsonManagedReference // assuming you're using Jackson databind JSON
    private List<Item> items;

}

А на стороне предмета:

@Entity
public class Item implements Serializable {
    @Id
    private int id;

    @JsonBackReference
    @ManyToOne
    @JoinColumn(name = "customer_Id")
    private Customer customer;

}

Тогда, если вы действительно обрабатываете данные JSON таким образом, вам нужен третий класс Entity для использования в качестве ResultSetMapping.

@Entity
@SqlResultSetMapping(
    name = "CustomerItem",
    entities = @EntityResult(entityClass = CustomerItem.class)
)
@NamedNativeQueries({
    @NamedNativeQuery(
        name = "CustomerItem.getAll",
        resultSetMapping = "CustomerItem"
        query = "select customer.id as cid, items.id as iid, customer.name,"
            + " items.itemName, items.itemPrice from testdb.customer INNER JOIN"
            + " items ON items.customer_Id = customer.id"
    )
})
public class CustomerItem implements Serializable {
    @Id
    private int cid;

    @Id
    private int iid;

    @Column
    private String name;

    @Column
    private String itemName;

    @Column
    private int itemPrice;

    ... getters and setters
}

Затем вы можете использовать собственный запрос в именованном варианте, который должен предложить некоторую небольшую оптимизацию.

List<CustomerItem> lst = em.createNamedQuery("CustomerItem.getAll", CustomerItem.class)
                               .getResultList();

Использование @SqlResultSetMapping означает, что возвращаемые сущности не отслеживаются на предмет изменений, но вы все равно можете использовать определенную сущность для результата. Я считаю, что по спецификации JPA он также должен работать без него, но в Hibernate это не так. Это может быть ошибка или запланированная, но не реализованная функция, или я могу просто неправильно интерпретировать использование JPA, но этот обходной путь работает с Hibernate 5+.

0 голосов
/ 05 ноября 2018

Не уверен насчет точной причины дубликатов, но SELECT DISTINCT решит вашу проблему, так как потребуются только отдельные записи.

См. using-Different-in-jpa

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...