![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
Sleepy_PIP |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 512 Регистрация: 30.6.2004 Где: Moscow Репутация: 3 Всего: 12 |
Хочу предложить общественности несколько тестов-примеров работы Хибернейт 3 ... ну и свои вопросы разумеется. я думаю для понимания и разбирательства - обязательно пригодиться.
Для начала - разборки с subclass ... Вариант - <subclass =========================================== Исходный файл маппинга: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="hb3"> <class name="Client" table="Clients" lazy="true"> <id name="id" type="long"> <generator class="native"/> </id> <discriminator column="typedef" type="string" force="true" /> <property name="name" type="string" length="30" /> <subclass name="Subclass1" lazy="true" discriminator-value="S"> <property name="add_f1" type="string" length="30" /> <property name="add_f2" type="long" /> </subclass> </class> </hibernate-mapping> ------------------------------------------------------------------------- схема БД, сгенерированная HB3 drop table Clients cascade constraints drop sequence hibernate_sequence create table Clients ( id number(19,0) not null, typedef varchar2(255) not null, name varchar2(30), add_f1 varchar2(30), add_f2 number(19,0), primary key (id) ) create sequence hibernate_sequence ========================================================================= Ввод данных: final SessionFactory sfactory = cfg.buildSessionFactory(); Session session = sfactory.openSession(); Transaction txn = session.beginTransaction(); Client p = new Client(); session.persist(p); /* тут издается select hibernate_sequence.nextval from dual */ p.setName("AAA"); Subclass1 sc= new Subclass1(); session.persist(sc); sc.add_f1="ddddd"; sc.setAdd_f2(21); session.flush(); /* update Clients set name=?, add_f1=?, add_f2=? where id=? */ txn.commit(); /* commit */ Выборка данных: Вариант1: получение всех данных. Использование данных вызывает выдачу select-а. long id=2; Client p= (Client) session.load(Client.class,new Long(id)); Subclass1 sc=(Subclass1)session.load(Subclass1.class,new Long(id)); System.out.println(p.getName()+" "+sc.getAdd_f2()); select client0_.id as id0_, client0_.name as name0_0_, client0_.add_f1 as add4_0_0_, client0_.add_f2 as add5_0_0_, client0_.typedef as typedef0_ from Clients client0_ where client0_.id=? and client0_.typedef in ('hb3.Client', 'S') Вариант2: получение данных только Subclass1ю Использование данных вызывает выдачу select-а long id=2; Client p= (Client) session.load(Client.class,new Long(id)); Subclass1 sc=(Subclass1)session.load(Subclass1.class,new Long(id)); System.out.println(sc.getAdd_f2()); select subclass1x0_.id as id0_, subclass1x0_.name as name0_0_, subclass1x0_.add_f1 as add4_0_0_, subclass1x0_.add_f2 as add5_0_0_ from Clients subclass1x0_ where subclass1x0_.id=? and subclass1x0_.typedef='S' Вариант3: попытка получения данных Subclass1 прямым доступом к полю. данные из БД не читаются long id=2; Client p= (Client) session.load(Client.class,new Long(id)); Subclass1 sc=(Subclass1)session.load(Subclass1.class,new Long(id)); System.out.println(sc.add_f2); select - отсутствует. данные не читаются Вариант4: теперь лениая инициализация запрещена. т.е. ... <class name="Client" table="Clients" lazy="false"> ... long id=2; Client p= (Client) session.load(Client.class,new Long(id)); select subclass1x0_.id as id0_, subclass1x0_.name as name0_0_, subclass1x0_.add_f1 as add4_0_0_, subclass1x0_.add_f2 as add5_0_0_ from Clients subclass1x0_ where subclass1x0_.id=? and subclass1x0_.typedef='S' /* данные зачитываются на момент загрузки объекта p, причем все данные - таким образом и объект sc оказывается инициализированным корректными данными из БД */ Subclass1 sc=(Subclass1)session.load(Subclass1.class,new Long(id)); System.out.println(sc.add_f2); /* выводятся актуальные данные */ ============================================= Добавлено @ 13:20 теперь <joined-subclass =========================================================== Исходный файл маппинга: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="hb3"> <class name="Client" table="Clients" lazy="true"> <id name="id" type="long"> <generator class="native"/> </id> <property name="name" type="string" length="30" /> <joined-subclass name="Subclass1" table="SC" lazy="true"> <key column="scID"/> <property name="add_f1" type="string" length="30" /> <property name="add_f2" type="long" /> </joined-subclass> </class> </hibernate-mapping> ------------------------------------------------------------------------------- Структура БД: drop table Clients cascade constraints drop table SC cascade constraints drop sequence hibernate_sequence create table Clients ( id number(19,0) not null, typedef varchar2(255) not null, name varchar2(30), primary key (id) ) create table SC ( scID number(19,0) not null, add_f1 varchar2(30), add_f2 number(19,0), primary key (scID) ) alter table SC add constraint FKA50ABF0B06B foreign key (scID) references Clients create sequence hibernate_sequence ============================================================================== Ввод данных: final SessionFactory sfactory = cfg.buildSessionFactory(); Session session = sfactory.openSession(); Transaction txn = session.beginTransaction(); Client p = new Client(); session.persist(p); /* select hibernate_sequence.nextval from dual */ p.setName("AAA"); Subclass1 sc= new Subclass1(); session.persist(sc); /* select hibernate_sequence.nextval from dua */ sc.add_f1="ddddd"; sc.setName("sssss"); sc.setAdd_f2(21); session.flush(); /* insert into Clients (name, id) values (?, ?) */ /* insert into Clients (name, id) values (?, ?) */ /* insert into SC (add_f1, add_f2, scID) values (?, ?, ?) */ /* update Clients set name=? where id=? */ /* update Clients set name=? where id=? */ /* update SC set add_f1=?, add_f2=? where scID=? */ txn.commit(); /* commit */ Выборка данных: Вариант1: Получение данных базового класса long id=2; p= (Client) session.load(Client.class,new Long(id)); sc=(Subclass1)session.load(Subclass1.class,new Long(id)); System.out.println(p.getName()); /* select client0_.id as id0_, client0_.name as name0_0_, client0_1_.add_f1 as add2_1_0_, client0_1_.add_f2 as add3_1_0_, case when client0_1_.scID is not null then 1 when client0_.id is not null then 0 end as clazz_0_ from Clients client0_ left outer join SC client0_1_ on client0_.id=client0_1_.scID where client0_.id=? */ System.out.println(sc.getAdd_f2()); /* корректный вывод данных сабкласса */ System.out.println(p.name); /* выводится null */ Вариант2: Получение данных сабкласса long id=2; p= (Client) session.load(Client.class,new Long(id)); sc=(Subclass1)session.load(Subclass1.class,new Long(id)); System.out.println(sc.getAdd_f2()); /* select subclass1x0_.scID as id0_, subclass1x0_1_.name as name0_0_, subclass1x0_.add_f1 as add2_1_0_, subclass1x0_.add_f2 as add3_1_0_ from SC subclass1x0_ inner join Clients subclass1x0_1_ on subclass1x0_.scID=subclass1x0_1_.id where subclass1x0_.scID=? */ /* вывод корректный */ System.out.println(p.getName()); /* вывод корректный */ System.out.println(sc.add_f2); /* вывод не корректный - поле не инициализировано */ System.out.println(p.name); /* вывод null */ Вариант3: Получение данных сабкласса с <class name="Client" table="Clients" lazy="fale"> long id=2; p= (Client) session.load(Client.class,new Long(id)); /* select client0_.id as id0_, client0_.name as name0_0_, client0_1_.add_f1 as add2_1_0_, client0_1_.add_f2 as add3_1_0_, case when client0_1_.scID is not null then 1 when client0_.id is not null then 0 end as clazz_0_ from Clients client0_ left outer join SC client0_1_ on client0_.id=client0_1_.scID where client0_.id=? */ sc=(Subclass1)session.load(Subclass1.class,new Long(id)); System.out.println(sc.getAdd_f2()); /* вывод корректный */ System.out.println(p.getName()); /* вывод корректный */ System.out.println(sc.add_f2); /* вывод корректный */ System.out.println(p.name); /* вывод корректный */ Добавлено @ 13:21 и наконец <union-subclass <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="hb3"> <class name="Client" table="Clients" lazy="true"> <id name="id" type="long"> <generator class="native"/> </id> <property name="name" type="string" length="30" /> <union-subclass name="Subclass1" table="SC" lazy="true"> <property name="add_f1" type="string" length="30" /> <property name="add_f2" type="long" /> </union-subclass> </class> </hibernate-mapping> ------------------------------------------------------------------------------- drop table Clients cascade constraints drop table SC cascade constraints drop sequence hibernate_sequence create table Clients ( id number(19,0) not null, name varchar2(30), primary key (id) ) create table SC ( id number(19,0) not null, name varchar2(30), add_f1 varchar2(30), add_f2 number(19,0), primary key (id) ) create sequence hibernate_sequence =============================================================================== Ввод данных: Client p = new Client(); session.persist(p); /* select hibernate_sequence.nextval from dual */ p.setName("AAA"); p.name="AAA"; Subclass1 sc= new Subclass1(); session.persist(sc); /* select hibernate_sequence.nextval from dual */ sc.add_f1="ddddd"; sc.setName("sssss"); sc.setAdd_f2(21); session.flush(); /* insert into Clients (name, id) values (?, ?) */ /* insert into SC (name, add_f1, add_f2, id) values (?, ?, ?, ?) */ /* update Clients set name=? where id=? */ /* update SC set name=?, add_f1=?, add_f2=? where id=? */ txn.commit(); /* commit */ Выборка данных Вариант1: long id=2; p= (Client) session.load(Client.class,new Long(id)); sc=(Subclass1)session.load(Subclass1.class,new Long(id)); System.out.println(sc.getAdd_f2()); /* select subclass1x0_.id as id0_, subclass1x0_.name as name0_0_, subclass1x0_.add_f1 as add1_1_0_, subclass1x0_.add_f2 as add2_1_0_ from SC subclass1x0_ where subclass1x0_.id=? */ /* вывод корректный */ System.out.println(p.getName()); /* вывод корректный */ System.out.println(sc.add_f2); /* вывод не корректный */ System.out.println(p.name); /* вывод null */ Добавлено @ 13:23
впрос с ходу - как к примеру в <joined-subclass избежать холостых update. ну они конечно не холостые, но не нужны совершенно, т.к. все можно было-б сделать в 1-х insert'ах ... а? -------------------- -- Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем свободным ..." |
|||
|
||||
Sleepy_PIP |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 512 Регистрация: 30.6.2004 Где: Moscow Репутация: 3 Всего: 12 |
продолжение. попытка борьбы с простым Set:
======================== Простой Set Исходный файл маппинга (заметим! - 1 на 2 класса!) <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="hb3"> <class name="ClientM1" table="Clients" lazy="true"> <id name="id" type="long"> <generator class="native"/> </id> <property name="name" type="string" length="30" /> <set name="phonesset"> <key column="client_id"/> <one-to-many class="Phone"/> </set> </class> <class name="Phone"> <id name="idphone"> <generator class="native"/> </id> <property name="Phone" type="string"/> <property name="Ph_type" type="short"/> </class> </hibernate-mapping> ------------------------------------------------------------------------------ Структура БД: drop table Clients cascade constraints drop table Phone cascade constraints drop sequence hibernate_sequence create table Clients ( id number(19,0) not null, name varchar2(30), primary key (id) ) create table Phone ( idphone number(19,0) not null, Phone varchar2(255), Ph_type number(5,0), client_id number(19,0), primary key (idphone) ) alter table Phone add constraint FK4984D4E37269893 foreign key (client_id) references Clients create sequence hibernate_sequence ============================================================================== Ввод данных: ClientM1 c = new ClientM1(); session.persist©; /* select hibernate_sequence.nextval from dual */ c.setName("AAA"); Phone ph=new Phone(); ph.setPh_type((short)1); ph.setPhone("abvgd"); c.getPhonesset().add(ph); session.persist(ph); /* select hibernate_sequence.nextval from dual */ session.flush(); /* insert into Clients (name, id) values (?, ?) */ /* insert into Phone (Phone, Ph_type, idphone) values (?, ?, ?) */ /* update Clients set name=? where id=? */ /* update Phone set client_id=? where idphone=? */ /* если не делать c.getPhonesset().add(ph) - insert into Phone все равно будут, только update Phone - уже не будет. и Phone окажется не привязанной к Client */ txn.commit(); /* commit */ Выборка данных: Вариант1: long id=1; c= (ClientM1) session.load(ClientM1.class,new Long(id)); System.out.println(c.name); /* null */ System.out.println(c.getName()); /* select clientm1x0_.id as id0_, clientm1x0_.name as name0_0_ from Clients clientm1x0_ where clientm1x0_.id=? */ Вариант2: Получение ClientM1 и всех связанных с ним Phone long id=1; c= (ClientM1) session.load(ClientM1.class,new Long(id)); ph=(Phone)c.getPhonesset().iterator().next(); /* select clientm1x0_.id as id0_, clientm1x0_.name as name0_0_ from Clients clientm1x0_ where clientm1x0_.id=? */ /* select phonesset0_.client_id as client4_1_, phonesset0_.idphone as idphone1_, phonesset0_.idphone as idphone0_, phonesset0_.Phone as Phone1_0_, phonesset0_.Ph_type as Ph3_1_0_ from Phone phonesset0_ where phonesset0_.client_id=? */ System.out.println(c.name); /* null */ System.out.println(c.getName()); /* корректные данные */ System.out.println(ph.phone); /* корректные данные */ System.out.println(ph.getPhone()); /* корректные данные */ Заметим, что данный вариант поднимает на клиета сразу все связанные с ClientM1 записи из Phones Вариант3: попытка перебрать записи Phone по одной long id=1; ClientM1 c1= (ClientM1) session.load(ClientM1.class,new Long(id)); Phone ph1; for(Iterator tt=c1.getPhonesset().iterator(); tt.hasNext();) /* select clientm1x0_.id as id0_, clientm1x0_.name as name0_0_ from Clients clientm1x0_ where clientm1x0_.id=? */ /* select phonesset0_.client_id as client4_1_, phonesset0_.idphone as idphone1_, phonesset0_.idphone as idphone0_, phonesset0_.Phone as Phone1_0_, phonesset0_.Ph_type as Ph3_1_0_ from Phone phonesset0_ where phonesset0_.client_id=? */ /* а вот далее - самое страшное - именно в этом месте начинают фетчиться _все_ записи по открытому 2-му select'у. Применение lazy в разных местах в разных значениях - не влияиет. Применение fetch в <set name="phonesset" lazy="false" fetch="select" > <key column="client_id" /> <one-to-many class="Phone"/> </set> с разными значениями - не влияет Применение <property name="hibernate.max_fetch_depth">0</property> <property name="hibernate.default_batch_fetch_size">4</property> <property name="hibernate.jdbc.fetch_size">10</property> с разными значениями - не влияет. И если есть 10000 записей - все они будут зачитаны из БД. */ { ph1=(Phone)tt.next(); System.out.println(ph1.getPhone()); System.out.println(c1.getPhonesset().size()); } ========================== Вопрос как добиться фетчения записей chield'а по 1 самостоятельно - открыт. ответа я пока нигде не нашел - может кто подскажет? А дальше надо будет удалить и/или изменить запись set-а без зачитывания всез записей из БД ... Это сообщение отредактировал(а) Sleepy_PIP - 8.7.2005, 11:45 -------------------- -- Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем свободным ..." |
|||
|
||||
Sleepy_PIP |
|
||||||||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 512 Регистрация: 30.6.2004 Где: Moscow Репутация: 3 Всего: 12 |
так, вроде-бы с коллекциями стало понятнее.
Вот рабочий пример отношения one-to-many через маппинг коллекции. parent - ClientM1, chield- Phone маппинг:
обратите внимание на inverse="true" и <many-to-one name="_client" column="client_id" not-null="true"/> CliemtM1:
обратите внимание на List phonesset=new Vector(); и public void addChild(Phone p) Phone:
обратите внимание на protected ClientM1 _client; теперь структура БД: create table Clients ( id number(19,0) not null, name varchar2(30), primary key (id) ) create table Phone ( idphone number(19,0) not null, Phone varchar2(255), Ph_type number(5,0), client_id number(19,0) not null, primary key (idphone) ) alter table Phone add constraint FK4984D4E37269893 foreign key (client_id) references Clients create sequence hibernate_sequence самое главное в ней - ничего лишнего ![]() теперь заполнение данными:
все insert-ты будут на session.flush(); (инициальзация - ленивая). в цикле будет только получение секвенсора а теперь самое главное, что не удавалось мне без полного fetch потомков - добавление нового Phone
на session.flush(); - всего один правильный insert ![]() но получение всех потомков все равно ведет к полной выборке:
на for(Iterator tt=c1.getPhonesset().iterator(); tt.hasNext();) - полная выборка По всей видимости разработчики не предпологали что надо иногда пройтись до N-й записи потомка _только_ ... такие вот дела. -------------------- -- Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем свободным ..." |
||||||||||||
|
|||||||||||||
FakIR |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 68 Регистрация: 8.3.2005 Репутация: нет Всего: нет |
Ниасилил. Ты хоть в начале КОД поюзай
![]() |
|||
|
||||
Sleepy_PIP |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 512 Регистрация: 30.6.2004 Где: Moscow Репутация: 3 Всего: 12 |
не понял тебя. я это все выдернул из моего рабочего примера. а ты о чем? -------------------- -- Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем свободным ..." |
|||
|
||||
iskan |
|
|||
Новичок Профиль Группа: Участник Сообщений: 26 Регистрация: 16.3.2005 Репутация: нет Всего: нет |
Help me please!
У меня saveOrUpdate при сохранении detached object instance даёт ошибку что мол такой объект уже есть. Заранее благодарен |
|||
|
||||
FakIR |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 68 Регистрация: 8.3.2005 Репутация: нет Всего: нет |
Я имею в виду ВВ "КОД" ато читать ооочень сложно...
|
|||
|
||||
парторг |
|
|||
Новичок Профиль Группа: Участник Сообщений: 33 Регистрация: 18.9.2005 Репутация: нет Всего: нет |
зачем вы используете xml-меппинги? есть же аннотации...
|
|||
|
||||
Zandr |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 433 Регистрация: 16.7.2004 Где: Новосибирск Репутация: 1 Всего: 13 |
Поподробне про inverse="true" можно? Нужно чтобы при апдейте детаченного объекта ассоциированные с ним ранее (но удаленные из коллекции в последствии) объекты удалялись. Ассоциация one-to-many (Set) Это из этой темы?
Добавлено @ 13:26 парторг, обобряю ![]() |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java tools & IDE's | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |