![]() |
|
Модераторы: LSD, AntonSaburov |
![]()
|
|
| aol |
|
||||||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 23.10.2008 Репутация: нет Всего: нет |
используется jsf
для примера есть 2 класса, user и car, то есть один юзер имеет много машин, ну и каждая машина имеет еще много фсего в отдельной таблице, для этого сделал у нее свой id и id юзера
нужно добавить новую машину к юзеру вытаскиваю юзера из сессии и
... один раз вроде добавляется ок, но потом Cannot persist detached object User, бывает и тоже самое для Car как понимаю нужно перед каждым persist делать сначала find для этого обьекта. но и он тоже выдает такую же ошибку, как правильно работать с этими персистанс обьектами ? спасибо Это сообщение отредактировал(а) aol - 23.10.2008, 21:49 |
||||||
|
|||||||
| v2v |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1620 Регистрация: 20.9.2006 Где: Киев Репутация: 9 Всего: 56 |
Я вобще - то этой спецификацией не пользуюсь, но кажется: persist используется при создании, дальше работает merge .
|
|||
|
||||
| aol |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 23.10.2008 Репутация: нет Всего: нет |
merge вроде для update можно использовать, не уверен
но он тоже не работает на форуме забугорном читал что persist да и по спецификации jpa, обьекты должны быть new, то есть новые перед каждым persist и тд.. но как их вытащить если em.find(Car.class, id) например тоже выдает ошибку такую. |
|||
|
||||
| powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
Не может find такую же ошибку выдавать. Максимум IllegalArgumentException может выдать. Метод merge так же как и метод persist сохраняет новый объект, если он действительно новый. Из спецификации:
Приведите ваш код полностью. |
|||
|
||||
| aol |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 23.10.2008 Репутация: нет Всего: нет |
прикрепил атачем, много там кода для страницы мне показалось.
класс Contract связан через форегн кей c User, работает отлично, при попытке сделать у контракта свой id и добавить поле с userId опять лезут ошибки JPABean `инджектиться` через faces-config.xml Присоединённый файл ( Кол-во скачиваний: 5 )
model.zip 5,63 Kb |
|||
|
||||
| powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
Во-первых, если Вы используете EJB 3.0, то почему не инжектируете через @PersistenseContext? Быть может лучше доверить управление транзакциями контейнеру?
Во вторых, заметил у Вас часто используются подобные строки кода:
Во-вторых, зачем делать refresh после find, да еще и в отдельной транзакции? Потом, каждый раз перед новой операцией (что было также замечено в коде) создавая новый EntityManager, Вы рискуете попасть на тот самый "detached object exception". Поскольку объект изначально был загружен в другом контексте, а значит связан с ним (с другим контекстом). При попытке вызова persist на detached объекте будет выброшено EntityExistsException. Решать такую проблему можно работая с одним экземпляром EntityManager в пределах всей бизнес-операции, т.е. методы для поиска/добавления/изменения на одном и том же экземпляре EntityManager в пределах одного (а иногда и нескольких) запросов. |
|||
|
||||
| aol |
|
||||||||||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 23.10.2008 Репутация: нет Всего: нет |
refresh в бине ContractManager в методе findContract для того чтобы после find, обновился обьект contract, так как если в базе например вручную изменить поле в данном случае готовности контракта, то без refresh он не обновляется и на экране видны старые данные.
а то что не на том месте, так это я ошибся, наверное так надо было
про EntityManager не знал что нужен один для всех, поэтому я JPABean закешировал путем помещения в файле faces-config.xml
и
а потом просто брал в бинах у которых это есть это свойство
то есть мне нужно просто перенести в эти бины обьект EntityManager, и как так обьявить ?
.. Это сообщение отредактировал(а) powerOn - 25.10.2008, 00:12 |
||||||||||
|
|||||||||||
| powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
Это весьма тонкий вопрос, относящийся к параллельно выполняемым задачам. Существует ряд проблем, если планируется что несколько потоков будут одновременно использовать одни данные, например Repetable Read или Phantom Insert. Они разрешается выставлением правильного уровня изоляции для транзакционного ресурса или/и блокировками. Посмотрите вот эту статейку.
К сожалению, с JSF я достаточно давно работал и успел его подзабыть. Но предполагаю, что JavaEE5 контейнер должен инжектировать EJB компоненты в JSF бины через @EJB аннотацию (вроде в JSF 1.2 это получалось). Если это так, то вам следует пойти таким путем. При этом EntityManager так же будет инжектирован в Ваши EJB. Транзакции открывать и закрывать самостоятельно не нужно, это сделает за Вас контейнер. Посмотрите аннотации @TransactionAttribute. |
|||
|
||||
| aol |
|
||||||||||||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 23.10.2008 Репутация: нет Всего: нет |
не очень понял про инжектировать EJB компоненты в JSF бины.
попробую описать как работает схема сейчас. есть в faces-config.xml следущие записи WelcomeBean просто класс в котором есть поле типа СontractBean
в свою очередь ContractBean содержит в себе 2 поля, contractManager как раз для работы с бд и Сontract - а это сам @Entity который и сохраняется
ContractManager имеет поле типа JPABean
а JPABean имеет жизненый цикл application, то есть живет пока сервак не умрет
а он просто вот что
на jsf есть такие выражения
когда с jsf, вызывается метод например #{WelcomePage.contractBean.createContract} то бины и их поля которые описаны данным образом в faces-config.xml создаются так называемым путем инжектирования, то есть бин ContractManager имеющий у себя поле типа private JPABean jpaBean и его сеттеры и геттеры public JPABean getJpaBean() { return jpaBean; } public void setJpaBean(JPABean jpaBean) { this.jpaBean = jpaBean; } после вызова соответсвующей jsp, может обращаться у своему свойству jpaBean, что я и делаю для записи обьекта в бд, получив от jpaBean EntityManager, EntityManager em = jpaBean.getEMF().createEntityManager(); а раз Вы говорите что EntityManager нужен для всех один, то значит мне просто нужно перенести сам EntityManager в бин который общается с бд, ContractManager @PersistenseContext EntityManager em; то есть эта запись равносильна EntityManager em = jpaBean.getEMF().createEntityManager(); или если напрямую то EntityManager em = Persistence.createEntityManagerFactory("portalJPA"); - что описано в persistace.xml ? прощу прощения что так фсе подробно, просто сам пытаюсь понять как это все должно работать ) Это сообщение отредактировал(а) aol - 25.10.2008, 01:10 |
||||||||||||
|
|||||||||||||
| powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
Точно так же как Вы инжектируете EntityManager в EJB компоненты с помощью аннотации @PersistenseContext, Вы можете инжектировать EJB компоненты в BackingBean-ы JSF. Проведите аналогию с инжектированием, которое происходит с JSF бинами, но только не нужно писать xml конфигурацию, контейнер получит всю необходимую информацию из аннотаций. Еще как вариант, самостоятельно создавать новый EntityManager (как это у Вас и было), но в request scope бине. При придется самостоятельно следить за транзакциями (открывать, закрывать), а во время Unit такой подход будет лишней палкой в колесе. Да, при этом имя персистент юнита можно указать в аннотации @PersistenseContext(unitName="portalJPA"). |
|||
|
||||
| aol |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 23.10.2008 Репутация: нет Всего: нет |
до конца не понимаю тогда в чем будет разница, то что я сейчас создаю EntityManager из обьекта который висит постоянно в application, и что если я перенесу создание EntityManager в сам бин только через аннотацию, то есть это одно тоже ?, и ошибка так же вылетать?
или вот еще, может тогда перенести EntityManager в JPABean который в application, то есть он будет возвращать не EntityManagerFactory, а сразу EntityManager, причем всегда один и тот же, так как закеширован.. так правильно вообще делать ? Это сообщение отредактировал(а) aol - 25.10.2008, 01:53 |
|||
|
||||
| powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
В application scope его не следует создавать, ведь так к нему будут обращаться потоки параллельно из нескольких запросов, что есть плохо. Желательно, сто бы каждый request имел свой EntityManager. На крайний случай можно создавать его в Session scoped бине, но только если этого требует логика. Если будете сами создавать EntityManager, то
|
|||
|
||||
| aol |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 23.10.2008 Репутация: нет Всего: нет |
ага, то есть если в бине будет
@PersistenseContext(unitName="portalJPA") EntityManager em; то это значит что я его не сам создаю ? то есть это не совсем одно и тоже как было раньше EntityManager em = jpaBean.getEMF().createEntityManager(); |
|||
|
||||
| powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
совершенно верно. его создаст контейнер и инжектирует в бин. p.s.: только что попробовал создать ear проект который содержит ejb модуль с EJB бином и web модуль с JSF страницей и managed bean-ом. EJB в JSF бины инжектируются, проверено. |
|||
|
||||
| aol |
|
||||||
|
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 23.10.2008 Репутация: нет Всего: нет |
убрал из всех бинов которые писали в бд
и добавил к ним поле
из faces-config.xml тоже убрал все записи про JPABean при попытке деплоя ear такая вот ошибка Deploying application in domain failed; The persistence-context-ref-name [portal.db.ContractManager/em] in module [] resolves to a persistence unit called [portalJPA] which is of type RESOURCE_LOCAL. Only persistence units with transaction type JTA can be used as a container managed entity manager. Please verify your application. вот мой persistance.xml
Это сообщение отредактировал(а) aol - 25.10.2008, 02:48 |
||||||
|
|||||||
![]()
|
| Правила форума "Java" | |
|
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |