У меня есть простой код, как:Повторяющиеся результаты с Hibernate, Spring, MySQL 5.7, Ломбок
@Transactional(readOnly = true, timeout = 10)
public List<MyClass> findThem() {
Criteria criteria = getSession().createCriteria(MyClass.class);
@SuppressWarnings("unchecked")
List<MyClass> theList = criteria.list();
return theList;
}
Когда я использую это для запроса, я получаю обратно 942 пунктов, с дублированием элементов в списке. Я не вижу шаблона, о котором они еще дублируются.
Если я напрямую обращаюсь к БД, я возвращаю 138 записей. 138 является правильное число результатов:
SELECT count(*) FROM theschema.MY_CLASS;
Я попытался с помощью класса и без Ломбок @EqualsAndHashCode(exclude="id")
на MyClass
, а также просто не включая любые equals()
реализацию, думая, что это дело - но не повезло.
Недавно я обновился от MySQL 5.6 до MySQL 5.7.17, но я все еще на Hibernate 4.3.8.Final и HikariCP 2.5.1. В запросе нет предложений WHERE
или что-то очень сложное. Это может быть неважно, но я нахожусь на весне 4.3.3.RELEASE с mysql-connector-java 5.1.39.
Любые другие предложения, где искать? Я собираюсь включить больше протоколов отладки и заглянуть ближе.
Update:
Я могу correct this с criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
, но не уверен, почему это сейчас необходимо.
Update 2
Вот MyClass
. У этого есть более основные свойства, но я вычитал их для краткости. Некоторые имена переименованы в целях конфиденциальности.
import base.domain.model.Persistable;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.validator.constraints.NotEmpty;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.*;
@NoArgsConstructor
@Entity
@Table(name = "MY_CLASS")
public class MyClass implements Persistable {
@Getter
@Setter
@Id
@Column(name = "MY_CLASS_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Getter
@Setter
private ClassB classb;
@Getter
@Setter
@ManyToOne
@JoinColumn(name = "CLASS_C_ID")
private ClassC classC;
@Getter
@Setter
@Transient
private Integer daysOpen;
@Getter
@Setter
@OneToOne
@JoinColumn(name = "CLASS_D_ID")
private ClassD classD;
@Getter
@Setter
@NotEmpty
private String briefDescription;
@Getter
@Setter
@Column(length = 1000)
private String details;
@Getter
@Setter
@OneToOne
@JoinColumn(name = "COMPANY_ID")
private Company company;
@Getter
@Setter
@Transient
private BigDecimal cost;
@Getter
@Setter
@ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinTable(name = "MY_CLASS_TAG",
foreignKey = @ForeignKey(name = "FK_MY_CLASS_TAG_REQUEST"),
joinColumns = @JoinColumn(name = "MY_CLASS_ID"),
inverseJoinColumns = @JoinColumn(name = "TAG_ID"))
private Set<Tag> tags = new HashSet<>(10);
@Getter
@Setter
@ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
@JoinTable(name = "MY_CLASS_ASSIGNEE",
foreignKey = @ForeignKey(name = "FK_MY_CLASS_ASSIGNEE"),
joinColumns = @JoinColumn(name = "MY_CLASS_ID"),
inverseJoinColumns = @JoinColumn(name = "ASSIGNEE_ID"))
private Set<Account> assignees = new HashSet<>(0);
@Getter
@Setter
@OneToMany(cascade = CascadeType.ALL, mappedBy = "myClass")
private List<MyClassHistory> historyList = new ArrayList<>(1);
private static final long serialVersionUID = 1L;
}
Update 3:
Я также возможность получить правильные результаты, используя HQL (сокращенная) без результата трансформатора:
String hql = "from MyClass myClass";
Query q = getSession().createQuery(hql);
List<MyClass> myClasses = q.list();
return myClasses;
Going сравнить вывод SQL для каждого (есть много результатов, чтобы попытаться понять).
Имеет ли ваш класс myclass много отношения к другому объекту. Если да, то он может дать вам повторяющиеся записи через спящий режим, если тип выборки определяется как нетерпеливый в отношениях от одного до многих. –
Проверьте http://stackoverflow.com/questions/1560239/is-it-valid-for-hibernate-list-to-return-duplicates – Justas
@PushpendraPal хорошая мысль, но нет типов выборки EAGER. – bphilipnyc