[Hibernate 3.2] Detached Objects

Pagina: 1
Acties:
  • 310 views sinds 30-01-2008
  • Reageer

  • NDF82
  • Registratie: Januari 2002
  • Laatst online: 28-11 20:53

NDF82

Doomed Space Marine

Topicstarter
Hi All,

Ik heb een probleem met detached objects. Stel ik heb de volgende classes.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ParentBean {
    @XmlAttribute
    private Long id;
    @XmlAttribute
    private Integer version;
    
    @XmlElement
    private String name;
    @XmlElement
    private Set<ChildBean> children;
    
    // constructors, getters and setters...
}

public class ChildBean {
    @XmlAttribute
    private Long id;
    @XmlAttribute
    private Integer version;
    
    @XmlElement
    private String name;

    // constructors, getters and setters...
}


En in mijn webservice stuur ik de volgende data naar de client:
code:
1
2
3
4
5
6
7
8
9
ParentBean
 |-id=1001
 |-name=parent 1
 |-version=1
 |-children
    |-ChildBean
       |-id=2001
       |-name=child 1
       |-version=1

De client verwerkt de data en besluit om de Parent naam te veranderen in "parent xyz". De client stuurt de volgende data terug naar de service.
code:
1
2
3
4
5
ParentBean
 |-id=1001
 |-name=parent xyz
 |-version=1
 |-children

De children moeten in de service genegeerd worden om overhead te voorkomen.

Hoe vertel ik hibernate om de children collectie te negeren?
saveOrUpdate(parentBean) aanroepen verwijderd alle bestaande children uit de database.
Eerst een session.lock(parentBean, SomeLockMode) zorgt voor een HibernateException("Iets in de trant van Dirty Collection Found")
Voor de saveOrUpdate(parentBean) de children initializeren met een new PersistentSet(session) in de hoop dat de children als niet lazy loaded worden beschouwd zorgt voor een HibernateException(Found two representations of same collection).

Wie o wie heeft het antwoord? Wie o wie kan mij naar artikelen/literatuur verwijzen die beschrijft hoe CRUD achtige webservices met JAX-WS en Hibernate te modelleren en te implementeren?

Pentium 233MHz MMX + Diamond Monster 3D 3DFX Voodoo II


  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 28-11 14:44
hibernate delete die collectie om dat je dat waarschijnlijk zo opgegeven hebt in je cascade instellingen, misschien kan je even de mapping posten

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • NDF82
  • Registratie: Januari 2002
  • Laatst online: 28-11 20:53

NDF82

Doomed Space Marine

Topicstarter
Ik gebruik idd cascade="all" omdat er ook momenten zijn dat ik er wel gebruik van wil maken. Dan wil ik kunnen zeggen:
code:
1
2
parent.getChildren().remove(someChild);
session.saveOrUpdate(parent);

Maar in de webservice wil ik children negeren.

Mijn .hbm:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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 schema="cfg" default-cascade="all,delete-orphan">
    <class name="SiteConfiguration" table="SiteConfiguration">

        <id name="id" column="id" type="long" unsaved-value="null" >
            <generator class="native" />
        </id>
        
        <version name="version"
                column="version"
                type="integer"
                unsaved-value="null" />
        
        <property name="name" 
                column="name" 
                type="string" />

        <set name="lineConfigurations" 
                table="LineConfiguration"
                cascade="all" >
            <key column="siteConfigurationId" />
            <one-to-many class="LineConfiguration" />
        </set>
    </class>
</hibernate-mapping>

Pentium 233MHz MMX + Diamond Monster 3D 3DFX Voodoo II


  • Tubby
  • Registratie: Juni 2001
  • Laatst online: 01-12 20:10

Tubby

or not to be

Je object eerst opnieuw ophalen uit de database, en vervolgens alleen de binnengekomen wijzigingen erop setten. Dat is de meest veilige manier :)

tubby.nl - Artes Moriendi - q1 - bf1942 - WoT - pubg - LinkedIN


  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 28-11 14:44
als je het enkel gebruikt om te wissen uit een collectie kan je gebruik maken van cascade="delete-orphan" ipv cascade="all"

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • NDF82
  • Registratie: Januari 2002
  • Laatst online: 28-11 20:53

NDF82

Doomed Space Marine

Topicstarter
Tubby schreef op donderdag 11 januari 2007 @ 10:13:
Je object eerst opnieuw ophalen uit de database, en vervolgens alleen de binnengekomen wijzigingen erop setten. Dat is de meest veilige manier :)
Dit is geen optie met betrekking tot onderhoud.
als je het enkel gebruikt om te wissen uit een collectie kan je gebruik maken van cascade="delete-orphan" ipv cascade="all"
Over het algemeen (lees "in de webapplicatie") wil ik wel gebruik maken van de cascade="all" optie. Maar in specifieke gevallen zoals de webservice interface wil ik deze setting omzeilen. In de webservice wil ik alleen de properties updaten, de relaties wil ik negeren.

Pentium 233MHz MMX + Diamond Monster 3D 3DFX Voodoo II


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Persoonlijk vind ik het een beetje vreemd dat je maar een gedeelte van de wijzigingen doorstuurd naar de db.

Laat jij verder de data van de webservice direct binden op je domain objects? Dit is imho niet goed. Je exposed daarmee veel te veel je domain layer. Ik zou persoonlijk een nieuwe data drager introduceren (DTO) waarop je vanuit de webservice data kunt binden. Deze data drager verstuur je door naar je service layer en in de service layer copieer je de inhoud van de velden (dus je houd 100% controle over wat er aangepast gaat worden en wat niet). Verder verhinder je de akelige 'saveOrUpdate' method op je application services:

http://peter.jteam.nl/?p=11

En je verhinder ook de thight coupling tussen client en server: je client is nu helemaal op de hoogte van je domain model, en iedere wijziging binnen je domain model, zal dus direct zichtbaar zijn binnen de clients (en dat is bad).

Ik denk dat je er beter aan doet om je aanpak te verbeteren, dan een quick fix erin te bakken.

[ Voor 59% gewijzigd door Alarmnummer op 11-01-2007 11:16 ]


  • NDF82
  • Registratie: Januari 2002
  • Laatst online: 28-11 20:53

NDF82

Doomed Space Marine

Topicstarter
Alarmnummer schreef op donderdag 11 januari 2007 @ 11:10:
Persoonlijk vind ik het een beetje vreemd dat je maar een gedeelte van de wijzigingen doorstuurd naar de db.
Niet een gedeelte van de wijzigingen, maar alleen dat gedeelte van de datastructuur welke gewijzigd is.
Laat jij verder de data van de webservice direct binden op je domain objects? Dit is imho niet goed. Je exposed daarmee veel te veel je domain layer. Ik zou persoonlijk een nieuwe data drager introduceren (DTO) waarop je vanuit de webservice data kunt binden. Deze data drager verstuur je door naar je service layer en in de service layer copieer je de inhoud van de velden (dus je houd 100% controle over wat er aangepast gaat worden en wat niet). Verder verhinder je de akelige 'saveOrUpdate' method op je application services:

http://peter.jteam.nl/?p=11
Ik heb je artikel gelezen wat een aantal vragen oproept.

In "Bypass business logic" vroeg ik me af of of het niet handiger is om
code:
1
public Employee update(SalaryUpdate update)throws SalaryTooHighException

te verplaatsen naar Employee. Door vervolgens de setSalary() te hiden kan het salaris alleen nog maar gezet worden middels business methods op het domein object. Hierdoor kan nog steeds gebruik gemaakt worden van de update() method op de manager interface. En wordt de SalaryUpdate DTO overbodig gemaakt.
En je verhinder ook de thight coupling tussen client en server: je client is nu helemaal op de hoogte van je domain model, en iedere wijziging binnen je domain model, zal dus direct zichtbaar zijn binnen de clients (en dat is bad).
Bedoel je dat je alleen DTOs zoals SalaryUpdate naar de client stuurt? En wanneer de client data wilt ophalen dmv een query wordt dan wel de structuur zoals in het domein model verstuurd?

Thanks voor je input.

Pentium 233MHz MMX + Diamond Monster 3D 3DFX Voodoo II


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

NDF82 schreef op donderdag 11 januari 2007 @ 11:52:
Ik heb je artikel gelezen wat een aantal vragen oproept.

In "Bypass business logic" vroeg ik me af of of het niet handiger is om
code:
1
public Employee update(SalaryUpdate update)throws SalaryTooHighException

te verplaatsen naar Employee.
De logica kan zeker naar de employee verhuist worden, of naar een SalaryUpdateService als de logica te complex is (zie domain service in DDD). Maar jouw application service definieerd wat jouw systeem kan, en lagen boven op jouw application service mogen alleen via deze laag aanroepen doen.

Als je het toe laat dat je direct calls op entities kan doen, dan loop je sowieso met security, transacties, en logging te kloten. Verder krijg je een tight coupling die imho onwenselijk is.
Door vervolgens de setSalary() te hiden kan het salaris alleen nog maar gezet worden middels business methods op het domein object. Hierdoor kan nog steeds gebruik gemaakt worden van de update() method op de manager interface. En wordt de SalaryUpdate DTO overbodig gemaakt.
Wie verhinderd dat alleen die business methode wordt aangeroepen? Via een application service heb jij volledig controle over wie wat aanroept.
Bedoel je dat je alleen DTOs zoals SalaryUpdate naar de client stuurt? En wanneer de client data wilt ophalen dmv een query wordt dan wel de structuur zoals in het domein model verstuurd?
Domain objecten naar clients versturen is imho vragen om problemen. Je loopt sowieso te kutten met hoe veel dat je gaat sturen. persoon.getvader().getvader().getVader().....

Wanneer ga je stoppen?

Verder heb je tight coupling tussen client en domain model, maw iedere wijziging binnen je domain model zal leiden tot een verandering bij de client. Het introduceren van een DTO kan dit probleem verhelpen doordat de DTO als een soortement van buffer functioneerd.
Thanks voor je input.
No problem

  • NDF82
  • Registratie: Januari 2002
  • Laatst online: 28-11 20:53

NDF82

Doomed Space Marine

Topicstarter
Alarmnummer schreef op donderdag 11 januari 2007 @ 12:10:
[...]

Domain objecten naar clients versturen is imho vragen om problemen. Je loopt sowieso te kutten met hoe veel dat je gaat sturen. persoon.getvader().getvader().getVader().....

Wanneer ga je stoppen?
Mijn retrieve method ziet er als volgt uit:
Java:
1
2
3
public interface ConfigurationWebService {
    public Configuration retrieve(final Configuration cfg, final int maxRetrieveDepth);
}

Java:
1
2
3
4
5
public class Configuration {
    private Set<MyDomainObject> myDomainObjects.

    // constructors, getters and setters
}


Een Configuration object/element heeft voor alle typen domein objecten List properties. Deze list properties bevatten examples (findByExample(...)) welke gebruikt zullen worden voor het uitvoeren van de query. De maxRetrieveDepth parameter geeft aan tot hoeveel niveuas diep de data wordt opgehaald.
Verder heb je tight coupling tussen client en domain model, maw iedere wijziging binnen je domain model zal leiden tot een verandering bij de client. Het introduceren van een DTO kan dit probleem verhelpen doordat de DTO als een soortement van buffer functioneerd.
Dit is nooit te voorkomen. Een eerste idee is dat alle wijzigingen bestaande code niet mogen breken (backwards compatible) en alle nieuwe properties optioneel moeten zijn.

Pentium 233MHz MMX + Diamond Monster 3D 3DFX Voodoo II


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

NDF82 schreef op donderdag 11 januari 2007 @ 14:32:
[...]

Mijn retrieve method ziet er als volgt uit:
Java:
1
2
3
public interface ConfigurationWebService {
    public Configuration retrieve(final Configuration cfg, final int maxRetrieveDepth);
}

Java:
1
2
3
4
5
public class Configuration {
    private Set<MyDomainObject> myDomainObjects.

    // constructors, getters and setters
}


Een Configuration object/element heeft voor alle typen domein objecten List properties. Deze list properties bevatten examples (findByExample(...)) welke gebruikt zullen worden voor het uitvoeren van de query. De maxRetrieveDepth parameter geeft aan tot hoeveel niveuas diep de data wordt opgehaald.
Hmm tja.. Als ik dit soort dingen zie, dan heb ik wel zo iets van 'waarom?'. Ik weet verder ook niet genoeg van je applicatie om er echt veel zinnigere dingen over te zeggen. Je hebt vaak van die technische applicaties die hele andere eisen stellen dan typische applicaties met een of andere domain.
Dit is nooit te voorkomen. Een eerste idee is dat alle wijzigingen bestaande code niet mogen breken (backwards compatible) en alle nieuwe properties optioneel moeten zijn.
Tja.. als het puur om properties gaat zonder enige vorm van inhoudelijke logica, en je wilt van buiten af properties kunnen beheren, dan is wellicht een DTO er tussen in overbodig. Dan is het in ieder geval geen standaard applicatie met de zoveelste domain model.

Verwijderd

Alarmnummer schreef op donderdag 11 januari 2007 @ 11:10:
Verder verhinder je de akelige 'saveOrUpdate' method op je application services:

http://peter.jteam.nl/?p=11
Beschrijf je nu hier het "Scattered Businesslogic Pattern"? ;)

  • NDF82
  • Registratie: Januari 2002
  • Laatst online: 28-11 20:53

NDF82

Doomed Space Marine

Topicstarter
Verwijderd schreef op donderdag 11 januari 2007 @ 21:14:
[...]

Beschrijf je nu hier het "Scattered Businesslogic Pattern"? ;)
Dit klinkt weer als een anti pattern.

Ik ben op zoek naar een (aantal) pattern(s) om CRUD achtige webservices te maken. Validatie is wel nodig, maar is niet erg complex (hoeft niet per property uitgevoerd te worden, per object is goed genoeg). Ik heb het idee dat ik het wiel opniew probeer uit te vinden.

Ik denk dat de interface waarnaar ik op zoek ben het beste met LDAP of iets dergelijks te vergelijken valt. Simpele, flexibele interface, maar wel getypeerd.

Pentium 233MHz MMX + Diamond Monster 3D 3DFX Voodoo II


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Verwijderd schreef op donderdag 11 januari 2007 @ 21:14:
[...]

Beschrijf je nu hier het "Scattered Businesslogic Pattern"? ;)
Nope. Ik beschrijf daar dat je alleen calls moet doen via je service layer van buiten af. Hoe dat binnen in is gerealiseerd is een andere zaak. Check anders service layer patterns van Patterns Of Enteprise Application Architecture of Application Layer van Domain Driven Design.

Verwijderd

Alarmnummer schreef op vrijdag 12 januari 2007 @ 09:43:
Nope. Ik beschrijf daar dat je alleen calls moet doen via je service layer van buiten af. Hoe dat binnen in is gerealiseerd is een andere zaak. Check anders service layer patterns van Patterns Of Enteprise Application Architecture of Application Layer van Domain Driven Design.
Er stond een knipoog bij heur...
Ik ben op de hoogte van DDD en ik ben er geen groot voorstander van. Het geeft je meer problemen dan het feitelijk oplost want je data schiet door nog meer lagen. Het is wat dat betreft alles behalve pragmatisch te noemen.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Verwijderd schreef op vrijdag 12 januari 2007 @ 12:31:
[...]
Er stond een knipoog bij heur...
Ik ben op de hoogte van DDD en ik ben er geen groot voorstander van. Het geeft je meer problemen dan het feitelijk oplost want je data schiet door nog meer lagen. Het is wat dat betreft alles behalve pragmatisch te noemen.
Hmm tja, heb ook nog steeds niet het gevoel van 'holy grail'. Maar als je alle eigenschappen van objecten via setters exposed, is het soms erg lastig om correcte objecten te krijgen/houden. Ik zit dus nog ergens halverwege.
Pagina: 1