Не объяснимое поведение hibernate.
При загрузке объектов (Link, Host, Service, Program), наследников класса (CheckObject) в рамках одной Hibernate сессии, некоторые объекты вместо родного класса (Link, Host, Service,Program) возвращают class.simpleClassName = CheckObject_$$_javaassist_19. При этом эксептионов нету :(.
Пока я только определил когда это происходит, но почему не могу понять :(.
Постараюсь сказать когда это происходит.
CheckObject имееет коллекцию childrens указывающую сама на себя, получается что-то вроде дерева типа:
Host1
childrens:
:---> Service1
:---> Service2
:---> Service3
Service1Service2
Service3
Host2
childrens:
:---> Program1
Program1
childrens
:---> Link
Link1 - Отличается от других ссылкой link на CheckObject!!!!
childrens: (нету)
link: - указывает на любой CheckObject
:-->
Service1Как только Link.link начинает содержать ссылку на CheckObject (потомки Link, Host, Service, Program)
Эти потомки при загрузке сстановятся не (Link, Host, Service, Program), а
CheckObject_$$_javaassist_19Я пробовал делать lazy=false и по умолдчанию (lazy=proxy), получается одно и тоже

.
Самое интересное, что никаких lazy exception не происходит!
Когда я загружаю hibernate-ом объекты, я делаю следующее:
1) сначала гружу корневые объекты (у которых нет parent - которые не являются чьими-то детками )
2) рекурсивно в рамках транзакции hibernate прохожу детей объекта тем, самым добиваюсь чтобы не было lazy exception и объекты загрузились.
Я думаю, что проблема где-то при загрузке данных. Видимо Link1 автоматом всё-таки грузит link=Service1 и когда грузится Host1-Service1, он уже имеет странный тип объекта :(.
Как победить данную проблему пока не знаю. Если у кого-то была подобная проблема ткните как вы грузили подобныве древовидные объекты со ссылками.
Код |
public List<CheckObject> findRootCheckObjects() { // TODO Auto-generated method stub HibernateTemplate session = getHibernateTemplate(); List<CheckObject> list = session.find( "select o from CheckObject o where o.parent=null" ); // lazy - false for (CheckObject checkObject : list) { findResurce_lazy_checkobject( checkObject ); } return list; }
/** * @param checkObject */ private void findResurce_lazy_checkobject( CheckObject checkObject ){ if( checkObject.getParent() instanceof Link){ return; } getHibernateTemplate().initialize( checkObject ); for (CheckObject element : checkObject.getChildrens()) { findResurce_lazy_checkobject (element);
} }
|
Прилагаю:
1) Файл описания hibernate
2) Файл класса CheckObject,
3) Файл класса Link
4) Файл класса Socket
5) Файл класса Host
Файл описания hibernate
Код |
<?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='ru.stb.sharov.monitor.check.domain'> <class name="CheckObject" table='monitorCheckObject' >
<id name="id" column="id" unsaved-value="0" > <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator"> <param name="sequence_name">monitorid_check_object</param> <param name="initial_value">100</param> </generator> </id>
<discriminator type="string" /> <many-to-one name="parent" column="parent_id" /> <!-- lazy="false" -->
<list name="childrens" cascade="all" > <!-- lazy="false" --> <key column="parent_id"/> <list-index column="child_index"/> <one-to-many class="CheckObject"/> </list>
<property name='name'/> <property name='enterPassword'/> <property name='tested'/>
<!-- <property name='status'/> <many-to-one name="status" column="status_id" /> --> <subclass name="Root" lazy="false" discriminator-value="root" > </subclass>
<subclass name="Section" lazy="false" discriminator-value="section" > </subclass>
<subclass name="Module" lazy="false" discriminator-value="module" > </subclass> <subclass name="Host" lazy="false" discriminator-value="host" > <property name='ip' /> </subclass> <subclass name="GroupIt" discriminator-value="groupIt" lazy="false" > </subclass> <subclass name="Program" discriminator-value="app" lazy="false" > </subclass> <subclass name="Socket" discriminator-value="socket" lazy="false" > <property name='ip' /> <property name='port' /> </subclass> <subclass name="Jdbc" discriminator-value="jdbc" lazy="false" > <property name='username' /> <property name='password' /> <property name='driverClassName' /> <property name='url' /> <property name='testSql' /> </subclass> <subclass name="Rmi" discriminator-value="rmi" lazy="false" > <property name='ip' /> <property name='port' /> <property name='serviceName' /> <property name='testMethod' /> <property name='testProperty' /> </subclass> <subclass name="Soap" discriminator-value="soap" lazy="false" > <property name='username' /> <property name='password' /> <property name='url' /> </subclass>
<subclass name="SoapSHSK" discriminator-value="soap-shsk" lazy="false" > <property name='username' /> <property name='password' /> <property name='url' /> <property name='nls' /> </subclass>
<subclass name="CorbaIask" discriminator-value="jaguar" lazy="false" > <property name='username' /> <property name='password' /> <property name='url' /> </subclass>
<subclass name="Http" discriminator-value="http" lazy="false" > <property name='trustStore' /> <property name='trustStorePassword' /> <property name='url' /> </subclass> <subclass name="Link" discriminator-value="connect" lazy="false" > <many-to-one name="link" /> </subclass>
</class>
|
2) Файл класса CheckObject
Код |
package ru.stb.sharov.monitor.check.domain;
import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List;
import ru.stb.sharov.monitor.domain.IdBaseObject;
/** Объект. * * @author sharov * */ public class CheckObject extends IdBaseObject implements Serializable { protected String enterPassword; /** Пароль просмотра содержимого элемента. */ public String getEnterPassword() { return enterPassword; } public void setEnterPassword(String enterPassword) { this.enterPassword = enterPassword; }
protected String name; protected CheckObject parent; protected List<CheckObject> childrens = new ArrayList<CheckObject>(); /** Вложенные объект проверки */ public List<CheckObject> getChildrens() { return childrens; } public void setChildrens(List<CheckObject> childrens) { this.childrens = childrens; }
/** Наименование объекта */ public String getName() { return (name==null?"": name); } public void setName(String name) { this.name = name; } /** Ссылка на родительсткий объект. */ public CheckObject getParent() { return parent; } public void setParent(CheckObject parent) { this.parent = parent; } public String toString() { return getTypeName()+" "+getName(); } /** Вернуть список ошибок валидации. * <li>key = имя свойства. * <li>value = ошибка. * @return массив key,value */ public HashMap<String, String> getValidateErrors(){ return null; }; /** Типы ожидаемых Вложенных объектов (Детей) * Определяет какие разрешены объекты в {@link #getChildrens()} * */ public CheckObject[] getTypeChildrens(){ return null; };
/** Имя типа элемента. * @return */ public String getTypeName() { return this.getClass().getSimpleName(); }
/** Признак того, что на объект может соединяться с другими объектами ({@link List}) */ public boolean getLinked(){ return false; } /** Признак того, что объект можено защищать паролём */ public boolean getSecured(){ return false; } /** Нужно ли наименование */ public boolean getNamed(){ return true; } /** Тестировать или нет. * Можно включить и выключить вручную * */ private Boolean tested = getNeedTested(); public Boolean getTested() { return (tested==null?false:tested); } public void setTested(Boolean tested) { this.tested = tested; } /** Нужно ли тестирование */ public Boolean getNeedTested() { return false; } private Status status; public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } }
|
3) Файл класса Link
Код |
package ru.stb.sharov.monitor.check.domain;
import java.util.HashMap;
/** Соединение с другими объектами. * * @author sharov * */ public class Link extends CheckObject{ CheckObject link;
/** ссылка на объект с которым соединяется элемент. * @return */ public CheckObject getLink() { return link; } public void setLink(CheckObject link) { this.link = link; }
@Override public String toString() { try { return getName()+"[link="+link+"]"; } catch (Exception e) { return getName(); } };
@Override public CheckObject[] getTypeChildrens() { return new CheckObject[]{}; } public String getTypeName() { return "Связь"; }
@Override public HashMap<String, String> getValidateErrors() { HashMap<String, String> errors = new HashMap<String, String>(); if(link == null){ errors.put("link", "Не выбран объект для соединения" ); } if(link == this ){ errors.put("link", "Нельзя выбрать соединение с самим собой" ); } return errors; } @Override public boolean getLinked() { return false; } @Override public boolean getNamed() { // TODO Auto-generated method stub return false; }
}
|
4) Файл класса Socket
Код |
package ru.stb.sharov.monitor.check.domain;
import java.util.HashMap;
/** Сервис типа Socket. * @author sharov */ public class Socket extends Host { int port; /** Порт сокета */ public int getPort() { return port; } public void setPort(int port) { this.port = port; } @Override public String getIp() { String parentIp = findParentIp( parent ); return ( parentIp==null? super.getIp() : parentIp) ; //return getIp(); }
private static CheckObject[] socketTypeChildrens = { new Link() }; public CheckObject[] getTypeChildrens() { return socketTypeChildrens; }
public String getTypeName(){ return "Сервис"; }
@Override public String toString() { return super.toString()+"[port=" + port + "]"; }
@Override public HashMap<String, String> getValidateErrors() { HashMap<String, String> errors = super.getValidateErrors(); if(port<=0 ){ errors.put("port", "Не указан Port сервиса" ); } return errors; } /** Находит IP родителя. * @param in - родительский объект * @return */ private String findParentIp(CheckObject in){ if( in==null) return null; if( in instanceof Host ) return ((Host)in).getIp(); else return findParentIp( in.parent ); }
public boolean getLinked(){ return true; } }
|
5) Файл класса Host
Код |
package ru.stb.sharov.monitor.check.domain;
import java.util.HashMap;
/** Сервер. * @author sharov */ public class Host extends CheckObject{ private String ip; public Host() { super(); }
private static CheckObject[] hostTypeChildrens = { new Rmi() ,new Program() ,new Socket() ,new Jdbc() ,new Soap() ,new Http() ,new CorbaIask() ,new SoapSHSK() ,new Module() ,new GroupIt() }; public CheckObject[] getTypeChildrens() { return hostTypeChildrens; }
/** IP Адрес сервера. * Если не определён, проверяет объект родитель {@link #getParent()}, если это {@link Host}, берёт его адрес. */ public String getIp() { return this.ip; } public void setIp(String ip) { this.ip = ip; }
public String getTypeName(){ return "Сервер"; } public String toString() { return super.toString()+" [ip=" + ip + "]"; }
public HashMap<String, String> getValidateErrors() { HashMap<String, String> errors = new HashMap<String, String>(); if(ip==null || ip.equals("")){ errors.put("ip", "Не указан IP адрес" ); } return errors; }
private int timeout = 5000; public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; }
@Override public Boolean getNeedTested() { return true; } }
|