Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Hibernate Set вместо List


Автор: eugeneu 4.4.2011, 18:32
Здравствуйте. Недавно стал использовать Hibernate3 в связке со Spring 3 в своем проекте.
Я использую аннотации для указания связей между сущностями и каждый раз делаю lazy initialization дабы не тянуть лишний раз данные. А если же они нужны то я делаю специальный HQL-запрос.
Рассмотрим следующий пример:


Имеется сущность "Сотрудник"
Код

@Entity
@Table(name = "employees")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "employee_id", nullable = false)
    private Long employeeId;

    @Column(name = "login", nullable = false)
    private String login;

    
    @ManyToMany(cascade = CascadeType.ALL,targetEntity=Authority.class, fetch=FetchType.LAZY)
    @JoinTable(name = "granted_authorities",  joinColumns = { @JoinColumn(name = "employee_id") },
               inverseJoinColumns = { @JoinColumn(name = "authority_id")})
    private List<Authority> authorities;


    public Employee() {
    }


    public Long getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(Long employeeId) {
        this.employeeId = employeeId;
    }

     

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }


    public List<Authority> getAuthorities() {
        
      
        return authorities;

    }

    public void setAuthorities(List<Authority> authorities) {

        this.authorities = authorities;

    }


}


Имеется сущность - "Разрешение"

Код

@Entity
@Table(name = "authorities")
public class Authority {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long authorityId;

    @Column(name = "name", nullable = false)
    private String authority;

    public String getAuthority() {
        return authority;
    }

    public void setAuthority(String authority) {
        this.authority = authority;
    }

    public Long getAuthorityId() {
        return authorityId;
    }

    public void setAuthorityId(Long authorityId) {
        this.authorityId = authorityId;
    }

}


Далее есть метод в котором я собственно получаю данные через HQL запрос:

Код

class EmployeeDAOImpl {

    public Employee getAuthorities(String login) throws HibernateException {
                
        Query query = sessionFactory.getCurrentSession().createQuery("from Employee e left join fetch e.authorities where e.login = ?");
        query.setString(0, login);
        
        List<Employee> employeeList = query.list();
        
        return employeeList.get(0);
    
    }
}


Много раз слышал, что получение List<> сущностей не есть хороший тон программирования - а хорошим тоном является получения Set<>.
Посути мне List не нужен - достаточно получить Set<Employee>.
Но не понятно как через HQL-запрос получить Set<Employee>, не брибегая к преобразованию List в Set.
Подскажите пожалуйста. заранее спасибо. 

Автор: tux 4.4.2011, 20:29
eugeneu, никак нельзя. В результатах запроса могут быть дубликаты, которые могут быть нужны приложению, поэтому org.hibernate.Query поддерживает только возврат списка. Возможно было бы полезным иметь какой-то convenient метод, который возвращал бы Set, но ведь преобразовать легко и самому:
Код

Set<Employee> employeeList = new HashSet(query.list());


Автор: Samotnik 4.4.2011, 21:21
Цитата(eugeneu @  4.4.2011,  18:32 Найти цитируемый пост)
Много раз слышал, что получение List<> сущностей не есть хороший тон программирования - а хорошим тоном является получения Set<>.

оригинально, а немного обоснования можно почему, чтобы это не выглядело голословно ? smile 

Автор: Старовъръ 4.4.2011, 21:36
Наоборот, работа с Set подразумевает http://community.jboss.org/wiki/EqualsandHashCode, связанных с реализацией equals() & hashCode(), так что я бы советовал везде использовать List вместо Set.

Автор: dobrolub 4.4.2011, 21:58
Set – подразумевает уникальность каждого елемента.

Автор: Samotnik 4.4.2011, 22:09
dobrolub, Старовъръ, в этом то и дело, на мой взгляд, утверждение:
Цитата(eugeneu @  4.4.2011,  18:32 Найти цитируемый пост)
получение List<> сущностей не есть хороший тон программирования - а хорошим тоном является получения Set<>

не совсем верно, потому что, это зависит от конкретной задачи. Когда нужен List, а когда Set.

Автор: dobrolub 4.4.2011, 22:40
Конечно. Set, например, подразумевает неупорядоченность элементов. В то время как List – упорядоченность. Тип должен улучшать читаемость программы, имно.

Автор: eugeneu 5.4.2011, 06:31
Постараюсь аргументировать...
В данном примере у "Сотрудника" может быть набор ролей - каждая из которых уникальна, если отслеживать уникальность "Ролей" при добавлении их "Сотруднику" то дубликатов быть не должно...
Если использовать List то мы тратим память на порядок записи в списке, а в данном случае это не требуется, достаточно просто получить массив. 
Вы правы в некоторых случаях действительно нужен List когда нужен порядок записей - в этом случае и буду использовать HQL.
Но если уйти от CreateQuery с HQL то как можно принудительно инициализовать набор "Разрешений" для "Сотрудника" получив при этом Set?

Автор: emmanuil 5.4.2011, 08:25
Немного отойду от темы.
eugeneu, в вашем примере, лучше возвращать unique, а не список, при получении Employee, так как логин уникальный.
Я в основном маппинг делаю через файл, замапьте authorities через set и хибер вернет вам set. Или если через аннотации, то укажите тип Set<>, должен вернуть set.
Еще чтобы получить set, можно у query через iterable и scroll самому вставлять объекты в свою коллекцию.
И еще у хибера есть класс Hibernate или HibernateUtils, в нем должен быть метод initialize, который инициализирует lazy свойства, если я не спутал.

Автор: eugeneu 5.4.2011, 09:01
Спасибо, попробую!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)