@Entity
public class Company{
int id;
String title;
@OneToMany(mappedBy="company", fetch=FetchType.EAGER,
cascade=CascadeType.ALL)
Set<Employee> employees;
[...]
}
@Entity
public class Employee{
int id;
String name;
@ManyToOne
Company company;
[...]
}
i zdalnego session beana :
@Stateful
public class CompanyManagerBean implements CompanyManagerRemote
{
public Company get(int id) {return em.find(Company.class,id);}
public Company store(Company c) {return em.merge(c);}
}
I robię coś takiego w kliencie :
Company c = companyManager.get(4343);
c.getEmployees().add(new Employee("Adam Kowalski"));
companyManager.store(c);
Efekt jest taki że w bazie pojawia się nowy pracownik Adam Kowalski, ale
jego pole company_id jest null. Przy ręcznym ustawianiu
employee.setCompany(c) wszystko jest ok. Co zrobić z tym fantem?
Używawam JBossa 4.2.2GA z domyślnym dostawcą JPA (Hibarnate EM)
>
> I robię coś takiego w kliencie :
>
> Company c = companyManager.get(4343);
> c.getEmployees().add(new Employee("Adam Kowalski"));
> companyManager.store(c);
>
> Efekt jest taki że w bazie pojawia się nowy pracownik Adam
> Kowalski, ale jego pole company_id jest null. Przy ręcznym
> ustawianiu employee.setCompany(c) wszystko jest ok. Co zrobić z
> tym fantem?
>
> Używawam JBossa 4.2.2GA z domyślnym dostawcą JPA (Hibarnate EM)
>
"Transparent POJO-oriented persistence implementations such as Hibernate do
not implement managed associations. Contrary to CMR, Hibernate associations are
all inherently unidirectional."
A to oznacza ze jezeli chcesz miec zwiazek dwukierunkowy, musisz okreslic zaleznosc dwukrotnie,
dla kazdej encji oddzielnie.
Zazwyczaj kod odpowiedzialny za wykonanie takiego powiazania umiejscawiany jest w jedej
metodzie:
class Company {
...
public void addEmployee(Employee empl) {
getEmployees().add(empl);
empl.setCompany(this);
}
}
Pozdrawiam
--
Jesli jeszcze nie zwariowales,
to znaczy ze jestes niedoinformowany.
> @Entity
> public class Company{
> int id;
> String title;
> @OneToMany(mappedBy="company", fetch=FetchType.EAGER,
> cascade=CascadeType.ALL)
> Set<Employee> employees;
Odpowiedź dostałeś już od Newiona, więc ja pozwolę sobie zapytać o coś
innego, ale wciąż związanego z Twoim przykładem.
1. Dlaczego użyłeś fetch=FetchType.EAGER?
2. Dlaczego użyłeś Set<Employee> zamiast List<Employee>?
Pytam, bo mam z czymś problem i sprowadziło się to do podobnych
rozwiązań co u Ciebie i stąd mam pytanie, czy decyzje były świadome i
również coś chciałeś zamodelować takimi konstrukcjami, czy po prostu tak
wyszło ;-)
> @Entity
> public class Employee{
> int id;
> String name;
> @ManyToOne
> Company company;
I to mnie również zastanawia. Użyłeś @ManyToOne dla stworzenia
dwukierunkowej asocjacji? Jeśli tak, to brakuje jeszcze elementu
mappedBy. Dla pojedyńczej nie jest to wymagane (muszę to jeszcze
sprawdzić, bo od wczoraj mam z tym mętlik).
Jacek
--
Jacek Laskowski
http://www.JacekLaskowski.pl
> 2. Dlaczego użyłeś Set<Employee> zamiast List<Employee>?
jezeli mapujesz kolekcje bez okreslonego porzadku, to po co List? Set jest
prostym zbiorem bez porzadku...
sam w "normalnym" programowaniu raczej korzystam z List, ale jakos przy
korzystaniu z hibernate/jpa zaczalem wykorzystywac Set do takich celow,
wystarczy zajrzec tez do przykladow tych technologi, wszedzie jest Set
jezeli kolekcje nie sa indeksowane...
Pozdrawiam
Brzezi
--
[ E-mail: brz...@enter.net.pl ][ ]
[ Ekg: #3781111 ][ ]
[ LinuxUser: #249916 ][ ]
> Cz, 29 lis 2007 o 08:54 GMT, Jacek Laskowski napisał(a):
>
>> 2. Dlaczego użyłeś Set<Employee> zamiast List<Employee>?
>
> jezeli mapujesz kolekcje bez okreslonego porzadku, to po co List? Set jest
> prostym zbiorem bez porzadku...
>
> sam w "normalnym" programowaniu raczej korzystam z List, ale jakos przy
> korzystaniu z hibernate/jpa zaczalem wykorzystywac Set do takich celow,
> wystarczy zajrzec tez do przykladow tych technologi, wszedzie jest Set
> jezeli kolekcje nie sa indeksowane...
Mam wrażenie, że Hibernate się buntuje, kiedy klasa persystentna zawiera
więcej niż jedną List i nie wyspecyfikuje się, na jakiej podstawie ma być
ustalana kolejność na tych listach.
--
Daniel 'Nathell' Janus, GG #1631668, przesu...@nathell.korpus.pl
create_initial_thread(initial_function);
lose("CATS. CATS ARE NICE.\n");
-- Steel Bank Common Lisp, sbcl/runtime/runtime.c:425
> 2. Dlaczego użyłeś Set<Employee> zamiast List<Employee>?
Przy relacjach wiele do jednego może nie ma to takiego znaczenia, ale w
relacjach wiele do wielu oszczędza to dużo pracu w pisaniu kodu
testującego czy elementy się nie powtarzają.
> I to mnie również zastanawia. Użyłeś @ManyToOne dla stworzenia
> dwukierunkowej asocjacji? Jeśli tak, to brakuje jeszcze elementu
> mappedBy. Dla pojedyńczej nie jest to wymagane (muszę to jeszcze
> sprawdzić, bo od wczoraj mam z tym mętlik).
Wydaje mi się że mappedBy powinny być tylko przy "właścicielu" czyli
Company. Ale głowy nie dam.
> Jacek
JK
>@Entity
>public class Company{
>int id;
>String title;
>@OneToMany(mappedBy="company", fetch=FetchType.EAGER,
>cascade=CascadeType.ALL)
>Set<Employee> employees;
>[...]
>}
>@Entity
>public class Employee{
>int id;
>String name;
>@ManyToOne
>Company company;
>[...]
>}
> Wydaje mi sie ze mappedBy powinny byc tylko przy "wlascicielu"
> czyli Company. Ale glowy nie dam.
>
> JK
>
Jest odwrotnie. mappedBy wskazuje nazwe atrybutu w encji bedacej wlascicielem relacji (czyli
mappedBy jest przy encji nie bedacej wlascicielem relacji).
Czyli w Twoim przykladzie wlascicielem relacji jest Employee.