Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос по работе с hibernate, @ManyToOne и другие 
:(
    Опции темы
MakTpaxep
Дата 25.12.2012, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 25.11.2010

Репутация: нет
Всего: нет



Две таблицы: users и tasks. 
Подскажите как реализовать такую штуку:
Есть user, который авторизовался при помощи spring security. Надо вытащить его ID.
Мне надо выбрать из tasks все строки связанные с текущим юзером через id. В tasks есть foreign key соответсвенно.

Извиняюсь если вопрос задан криво или не точно. Тут такое обилие технологий, спобосов разных, я запутался.

UPD
Ну вот вроде сам чуть-чуть разобрался. Сделал запрос при помощи criteria. Смотрится конечно не очень. Как обычный запрос.
 
Код

       Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Task.class);
        criteria.add(Restrictions.eq("assignee_user_id", 100));
        return criteria.list();

Остался только вопрос где взять ID текущего пользователя.
Имя я беру через principle.
Думаю можно сделать ещё один запрос и я получу ID.

Но всё-таки я что-то не то делаю...

Это сообщение отредактировал(а) MakTpaxep - 26.12.2012, 00:21
PM MAIL   Вверх
MisterCleric
Дата 26.12.2012, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Привет. Если ты используешь Spring Security & JDBC DaoAuthenticationProvider, то можешь написать кастомную реализацю JdbcDaoImpl, где кроме логин/пароль, можешь вытащить еще и ИД и своего кастомного запроса. 
Примерно так:
Код

<security:authentication-manager alias="authenticationManager" erase-credentials="true">
        <security:authentication-provider ref="daoAuthenticationProvider"/>
    </security:authentication-manager>

    <bean id="daoAuthenticationProvider"
          class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="myUserService"/>
    </bean>

    <bean id="myUserService" class="com.my.project.security.MyJdbcDaoImpl"
          p:dataSource-ref="dataSource"
          p:rolePrefix="ROLE_"
          p:usersByUsernameQuery="SELECT login, password, id FROM users WHERE login = ?"
          p:authoritiesByUsernameQuery="SELECT login, authority FROM authorities WHERE login = ?"/>

Код

public class MyJdbcDaoImpl extends JdbcDaoImpl {

    private MappingSqlQuery usersByUsernameMapping;

    @Override
    protected void initDao() throws ApplicationContextException {
        super.initDao();
        this.usersByUsernameMapping = new UsersByUsernameMapping(getDataSource());
    }

    protected List loadUsersByUsername(String username) {
        return usersByUsernameMapping.execute(username);
    }

    @Override
    protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery, List<GrantedAuthority> combinedAuthorities) {
        return new MyUser(username, userFromUserQuery.getPassword(), ((MyUser) userFromUserQuery).getId(), combinedAuthorities);
    }

    private class UsersByUsernameMapping extends MappingSqlQuery {
        protected UsersByUsernameMapping(DataSource ds) {
            super(ds, getUsersByUsernameQuery());
            declareParameter(new SqlParameter(Types.VARCHAR));
            compile();
        }

        protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
            String username = rs.getString(1);
            String password = rs.getString(2);
            Long id = rs.getLong(3);
            return new MyUser(username, password, clientId, AuthorityUtils.NO_AUTHORITIES);
        }
    }
}


И дальше твой principle как раз и есть этот объект MyUser.

Не смотрел: может в 3.2 это поменяется, чтобы быть проще.


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
MakTpaxep
  Дата 26.12.2012, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 25.11.2010

Репутация: нет
Всего: нет



Спасибо за совет.
Идею я уловил, но в коде пока что много для меня непонятного. Решил пока к себе не пересаживать)
Вся соль в этом кусе как я понял?
Код

        protected UsersByUsernameMapping(DataSource ds) {
            super(ds, getUsersByUsernameQuery());
            declareParameter(new SqlParameter(Types.VARCHAR));
            compile();
        }

Ну вообщем действительно сложновато. Для меня по крайней мере.

Сейчас я сделал как и планировал два запроса:
В TasksDAO
Код

    public List<Task> getTasksOfCurrentUser(String username)
    {
        List<User> list = sessionFactory.getCurrentSession().createQuery("from User x where x.username = '"+username+"'").list();        
        int currentUserId = list.get(0).getId();
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Task.class);
        criteria.add(Restrictions.eq("assignee_user_id", currentUserId));
        return criteria.list();
    }

А в контроллере так 
Код

    public ModelAndView getTasksOfCurrentUser(Principal principal)
    {       
        String username = principal.getName();        
        ModelAndView mav = new ModelAndView("showTasks");
        List<Task> tasks = tasksDAO.getTasksOfCurrentUser(principal.getName());
        mav.addObject("TASKS", tasks);
        return mav;
    }

Работает. Вот так вот))

Раз уже эта тема про гибернейт - поястине, пожалуйста, какая разница как делать запросы через гибернейт:
У себя совместил два подхода где-то подсмотренных (createQuery и criteria. А есть ещё что-то в духе hibernateTemplate.

UPD
А ещё мне очень понравилось вот это:
Код

    public Task getById(int id)    {
        return (Task) sessionFactory.getCurrentSession().get(Task.class, id);
    }  

Так кратко)

Это сообщение отредактировал(а) MakTpaxep - 26.12.2012, 17:02
PM MAIL   Вверх
MisterCleric
Дата 26.12.2012, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



createQuery: рекомендую использовать это для сложных статических запросов.
criteria: подходит для запросов по одной Entity с вариантами фильтрации, сортировки и пейджирования.
hibernateTemplate: умер этот подход. В Spring 3.1 уже не рекомендуют его использовать.
getById(int id): ничего удивительного. В конечном итоге просто запрос на одну Entity по ее ИД.

А то, что ты выкрутился через дополнительный запрос для, так ничего удивителнього: пусть будет - лишь бы работало как надо  и быстро.
Бывает и хуже.

Цитата

Вся соль в этом кусе как я понял?

Да, ну кастомная реализация класса User из Spring Security


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
MakTpaxep
Дата 26.12.2012, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 25.11.2010

Репутация: нет
Всего: нет



Спасибо, за объяснения! Сам бы искал очень долго.

Появился ещё вопрос связанный с гибернейтом:
При попытке сохранить новый экземпляр сущности выдаётся ошибка
Код

 Column 'ASSIGNEE_USER_ID' specified twice

Ругается из-за того, что в классе сущности у меня такие записи:
Код

    @ManyToOne
    @JoinColumn(name = "ASSIGNEE_USER_ID")
    private User assignee;

    @Column(name = "ASSIGNEE_USER_ID")
    private int assignee_id;

Первая используется чтобы во вьюшке можно было писать
Код

<c:out value="${task.assignee.username}"></c:out>

То есть чтобы сразу обращаться к объекту юзера, а не доставать его лишний раз через ID.

А без второй записи я не знаю как записать объект в БД. Когда я сохраняю новый Task, нужны все поля.
Вот какую штуку я сделал в форме, чтобы было удобно заполнять assignee_id
Код

<form:select path="assignee_id">
    <c:forEach items="${USERS}" var="USER"> 
        <form:option label="${USER.username}" value="${USER.id}"/>
    </c:forEach>    
</form:select>   

Как теперь выкручиваться?

UPD
Дошёл своими умом переборов вариантов. Везде где подразумевается колонка, можно использовать assignee.id
Вот примеры:
Код

        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Task.class);
        criteria.add(Restrictions.eq("assignee.id", id));

Код

<form:form action="add" commandName="NEWTASK" method="post">
<form:select path="author.id">
    <c:forEach items="${USERS}" var="USER"> 
        <form:option label="${USER.username}" value="${USER.id}"/>
    </c:forEach>    
</form:select>  
........

Круто

Это сообщение отредактировал(а) MakTpaxep - 26.12.2012, 20:50
PM MAIL   Вверх
MisterCleric
Дата 26.12.2012, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Цитата

Ругается из-за того, что в классе сущности у меня такие записи:

Должно быть так:
Код

@JoinColumn(name = "ASSIGNEE_USER_ID", insertable = false, updatable = false)
    private User assignee;



--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0768 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.