On a fait un appli, utilisant Struts1.2 et Hibernate 3.
Il y a une page, par laquelle on insère un Customer objet, et après tant de difficultés confrontées pour se débrouiller avec les différents Customer properties. Je viens d'être coincées en se débrouillant avec le property nommé Partner dont le Customer peut avoir plusieurs.
Voilà les mapping files de Customer, Partner:
Customer.hbm.xml:
Partner.hbm.xml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse - Hibernate Tools --> <hibernate-mapping> <class name="com.primasoft.housing.model.Customer" table="CUSTOMER" schema="HOUSE"> <id name="customerId" type="long"> <column name="CUSTOMER_ID" precision="22" scale="0" /> <generator class="increment" /> </id> <property name="customerName" type="string"> <column name="CUSTOMER_NAME" length="300" /> </property> <many-to-one name="customer" class="com.primasoft.housing.model.Customer" fetch="select"> <column name="PARENT_CUSTOMER_ID" precision="22" scale="0" /> </many-to-one> <set name="realEstateAssignTranses" inverse="true"> <key> <column name="CUSTOMER_ID" precision="22" scale="0" /> </key> <one-to-many class="com.primasoft.housing.model.RealEstateAssignTrans" /> </set> <set name="wifes" inverse="true" > <key> <column name="CUSTOMER_ID" precision="22" scale="0" /> </key> <one-to-many class="com.primasoft.housing.model.Wife" /> </set> <set name="childs" inverse="true" > <key> <column name="CUSTOMER_ID" precision="22" scale="0" /> </key> <one-to-many class="com.primasoft.housing.model.Child" /> </set> <set name="customers" inverse="true"> <key> <column name="PARENT_CUSTOMER_ID" precision="22" scale="0" /> </key> <one-to-many class="com.primasoft.housing.model.Customer" /> </set> <set name="partners" inverse="true" > <key> <column name="CUSTOMER_ID" precision="22" scale="0" /> </key> <one-to-many class="com.primasoft.housing.model.Partner" /> </set> </class> </hibernate-mapping>
Ce Partner class a 2 classes; Country et PartnerLegalType qui référencent une One-to-Many relation. Ça veut dire que Country et PartnerLegalType sont des look up tables.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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"> <!-- Mapping file autogenerated by MyEclipse - Hibernate Tools --> <hibernate-mapping> <class name="com.primasoft.housing.model.Partner" table="PARTNER" schema="HOUSE"> <id name="partnerId" type="long"> <column name="PARTNER_ID" precision="22" scale="0" /> <generator class="increment" /> </id> <many-to-one name="partnerLegalType" class="com.primasoft.housing.model.PartnerLegalType" fetch="select"> <column name="PARTNER_LEGAL_TYPE_ID" precision="22" scale="0" /> </many-to-one> <many-to-one name="customer" class="com.primasoft.housing.model.Customer" fetch="select"> <column name="CUSTOMER_ID" precision="22" scale="0" /> </many-to-one> <many-to-one name="country" class="com.primasoft.housing.model.Country" fetch="select"> <column name="COUNTRY_ID" precision="22" scale="0" /> </many-to-one> <property name="partnerName" type="string"> <column name="PARTNER_NAME" length="300" /> </property> <property name="partnerShare" type="string"> <column name="PARTNER_SHARE" length="200" /> </property> </class> </hibernate-mapping>
PartnerLegalType.hbm.xml:
Country.hbm.xml:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse - Hibernate Tools --> <hibernate-mapping> <class name="com.primasoft.housing.model.PartnerLegalType" table="PARTNER_LEGAL_TYPE" schema="HOUSE"> <id name="partnerLegalTypeId" type="long" > <column name="PARTNER_LEGAL_TYPE_ID" precision="22" scale="0" /> <generator class="native"/> </id> <property name="partnerLegalTypeName" type="string"> <column name="PARTNER_LEGAL_TYPE_NAME" length="100" /> </property> <set name="partners" inverse="true"> <key> <column name="PARTNER_LEGAL_TYPE_ID" precision="22" scale="0" /> </key> <one-to-many class="com.primasoft.housing.model.Partner" /> </set> </class> </hibernate-mapping>
Le scénario n'oblige pas l'utilisateur en insérant ce nouveau Partner de choisir son Country ou PartnerLegalType, qui sont exposés dans des combo box.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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"> <!-- Mapping file autogenerated by MyEclipse - Hibernate Tools --> <hibernate-mapping> <class name="com.primasoft.housing.model.Country" table="COUNTRY" schema="HOUSE"> <id name="countryId" type="long"> <column name="COUNTRY_ID" precision="22" scale="0" /> <generator class="native"/> </id> <property name="countryName" type="string"> <column name="COUNTRY_NAME" length="50" /> </property> <set name="customers" inverse="true"> <key> <column name="COUNTRY_ID" precision="22" scale="0" /> </key> <one-to-many class="com.primasoft.housing.model.Customer" /> </set> <set name="partners" inverse="true"> <key> <column name="COUNTRY_ID" precision="22" scale="0" /> </key> <one-to-many class="com.primasoft.housing.model.Partner" /> </set> </class> </hibernate-mapping>
D'ici, quand j'insère un nouveau Customer, et par la conséquence un nouveau Partner, une org.hibernate.TransientObjectException est confrontée quand le Partner insertion commit est exécuté:
Je sais que l'utilisateur n'a pas choisi la valeur du Country ou du PartnerLegalType si leurs ID=-100.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 //Partners TreeMap partnersCopy=customerInfoForm.getPartnersCopy(); Set partnersSet=partnersCopy.keySet(); Iterator partnersSetIterator=partnersSet.iterator(); while (partnersSetIterator.hasNext()) { Partner partner = (Partner)partnersCopy.get((String)partnersSetIterator.next()); //Checkin if the end user submitted the map with only 1 row contaning nothing, cos such case will add empty data in the database //Only customers with category 2شركات can have partners, so we check customer category also if ((partnersCopy.size()>1||(partnersCopy.size()==1&&!partner.getPartnerName().equals("")))&&custCat.equals(new Long("2"))) { //Setting the master customer id before saving the partner object. partner.getCustomer().setCustomerId(customer.getCustomerId()); //In case the same customer is inserted once again with a different code, we have to allow partners to be inserted also partner.setPartnerId(null); //Setting -100 values with null if (partner.getCountry().getCountryId().equals(new Long("-100"))) { partner.getCountry().setCountryId(null); } if (partner.getPartnerLegalType().getPartnerLegalTypeId().equals(new Long("-100"))) { partner.getPartnerLegalType().setPartnerLegalTypeId(null); } Transaction transaction2 = saveOrUpdateSession.beginTransaction(); saveOrUpdateSession.saveOrUpdate(partner); transaction2.commit(); } }
et voici l'exception:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 org.hibernate.TransientObjectException: com.primasoft.housing.model.PartnerLegalType at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:216) at org.hibernate.type.EntityType.getIdentifier(EntityType.java:108) at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:221) at org.hibernate.type.TypeFactory.findDirty(TypeFactory.java:476) at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:2803) at org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:467) at org.hibernate.event.def.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:190) at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:113) at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:195) at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1009) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:356) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) at com.primasoft.housing.transactions.CustomerInfoTransaction.insertOrUpdateCustomer(CustomerInfoTransaction.java:528) at com.primasoft.housing.action.CustomerInfoAction.execute(CustomerInfoAction.java:70) at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1192) at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at com.evermind.server.http.ResourceFilterChain.doFilter(ResourceFilterChain.java:65) at oracle.security.jazn.oc4j.JAZNFilter.doFilter(Unknown Source) at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:663) at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:330) at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:830) at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:285) at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:126) at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192) at java.lang.Thread.run(Thread.java:534)
Partager