Avatar billede billen Nybegynder
31. marts 2004 - 22:50 Der er 47 kommentarer og
1 løsning

Indsættelse af relationsdata i et mange-til-mange forhold

Jeg har to entiteter der har følgende forhold:

File *-----* Info (altså mange til mange)

Dette er løst fint nok med CMP og CMR og jeg kan sagtens få de data ud der er i de to entiteter (tre tabeller).

Men de data har indtil videre været sat ind manuelt i databasen. Nu vil jeg gerne have det til at foregå via entiterne i stedet. Som det er nu kan jeg kun arbejde med en collection på hver side af relationen. Men hvad nu hvis jeg gerne bare vil tilføje en enkelt Info til min File? Kan jeg det?

Jeg har forsøgt at lave en Collection af Info og giver den til File ved hjælp af file.setInfos(collection). Men det giver følgende fejl:

WARN  [TxConnectionManager] Prepare called on a local tx. Use of local transactions on a jta transaction with more than one branch may result in inconsistent data in some cases of failure.


Puh ha, det var mange ting. Spørg hvis jeg skal uddybe.
Avatar billede arne_v Ekspert
02. april 2004 - 14:52 #1
Selve fejl meddelelsen antyder bare at I har defineret en local-tx-datasource
i xxxx-ds.xml og at I har brug for en xa-datasource.

Men jeg ved ikke om jeg er overbevist om det at det er fejlen.
Avatar billede billen Nybegynder
03. april 2004 - 10:11 #2
Nej, dagen efter gav den ikke den fejlmeddelse igen. Men jeg kan stadigvæk ikke finde ud af at indsætte data i relationstabellen via CMP/CMR.

Min midligertidige løsning er at gøre det i hånden (JDBC).

arne_v: Jeg har kigget dit eksempel på CMR igennem og der har du mange til mange relationer. Du har lagt data direkte ind i tabellerne. Men ved du hvordan man gør det ved hjælp af ens entity beans?
Avatar billede arne_v Ekspert
03. april 2004 - 11:41 #3
Jeg tror at man bare laver normal 2 x create + 2 x set.

Men jeg kan godt prøve at se om jeg kan få det til at virke
Avatar billede arne_v Ekspert
03. april 2004 - 12:25 #4
Jep - det virker fint.

Koden kommer nu.
Avatar billede arne_v Ekspert
03. april 2004 - 12:25 #5
package test;

import javax.ejb.*;
import java.util.*;
import java.rmi.*;

public interface Lookup extends javax.ejb.EJBObject {
    public HashMap lookup() throws RemoteException;
    public void add(int id, String navn, String besk) throws RemoteException;
}
Avatar billede arne_v Ekspert
03. april 2004 - 12:25 #6
package test;

import java.util.*;

import javax.ejb.*;
import javax.naming.*;

public class LookupBean implements SessionBean {
    SessionContext sessionContext;
    public void ejbCreate() throws CreateException {
    }
    public void ejbRemove() {
    }
    public void ejbActivate() {
    }
    public void ejbPassivate() {
    }
    public void setSessionContext(SessionContext sessionContext) {
        this.sessionContext = sessionContext;
    }

    public HashMap lookup() {
        HashMap res = new HashMap();
        try {
            Context ctx = new InitialContext();
            BilHome home = (BilHome) ctx.lookup("local/Bil");
            Iterator bilit = home.findAll().iterator();
            while (bilit.hasNext()) {
                Bil bilbean = (Bil) bilit.next();
                Iterator beskit = bilbean.getBeskrivelse().iterator();
                StringBuffer sb = new StringBuffer("");
                while(beskit.hasNext()) {
                    Beskrivelse beskbean = (Beskrivelse) beskit.next();
                    if(sb.length() > 0) sb.append(" ");
                    sb.append(beskbean.getBeskrivelse());
                }
                res.put(bilbean.getNavn(), sb.toString());
            }
        } catch (NamingException ex) {
            ex.printStackTrace();
        } catch (FinderException ex) {
            ex.printStackTrace();
        }
        return res;
    }
   
    public void add(int id, String navn, String besk) {
        try {
            Context ctx = new InitialContext();
            BilHome bilhome = (BilHome) ctx.lookup("local/Bil");
            BeskrivelseHome beskhome = (BeskrivelseHome) ctx.lookup("local/Beskrivelse");
            Bil bilbean = bilhome.create(new Integer(id));
            bilbean.setNavn(navn);
            Collection bilbesk = bilbean.getBeskrivelse();
            StringTokenizer st = new StringTokenizer(besk, ",");
            while (st.hasMoreTokens()) {
                int beskid = Integer.parseInt(st.nextToken());
                Beskrivelse beskbean = beskhome.findByPrimaryKey(new Integer(beskid));
                bilbesk.add(beskbean);
            }
            bilbean.setBeskrivelse(bilbesk);
        } catch (NamingException ex) {
            ex.printStackTrace();
        } catch (FinderException ex) {
            ex.printStackTrace();
        } catch (CreateException ex) {
            ex.printStackTrace();
        }
    }
}
Avatar billede arne_v Ekspert
03. april 2004 - 12:25 #7
import java.rmi.*;
import java.util.*;

import javax.ejb.*;
import javax.naming.*;
import javax.rmi.*;

import test.*;

public class TestCMR {
    public static void main(String[] args) {
        System.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
        System.setProperty("java.naming.factory.url.pkgs", "org.jnp.interfaces");
        System.setProperty("java.naming.provider.url", "localhost:1099");
        try {
            Context ctx = new InitialContext();
            Object temp = ctx.lookup("Lookup");
            LookupHome home = (LookupHome) PortableRemoteObject.narrow(temp, LookupHome.class);
            Lookup bean = home.create();
            HashMap hm;
            hm = bean.lookup();
            System.out.println(hm);
            bean.add(7, "Lamborghini", "1,5");
            hm = bean.lookup();
            System.out.println(hm);
        } catch (ClassCastException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (NamingException e) {
            e.printStackTrace();
        } catch (CreateException e) {
            e.printStackTrace();
        }
    }
}
Avatar billede arne_v Ekspert
03. april 2004 - 12:26 #8
Entity beans'ene og deployment descriptorerne er uændrede.
Avatar billede arne_v Ekspert
03. april 2004 - 12:30 #9
På en skala fra 00 til 13 står den add metode naturligvis til -10 i brugervenlighed
(der skal naturligvis kun angives navne og ikke id'er som argumenter !).

Men teknikken inde i add metoden er god nok og det er det I leder efter.

get collection
add bean til collection
set collection

CMP ordner resten.
Avatar billede billen Nybegynder
03. april 2004 - 13:51 #10
Jeg kigger på det i løbet af dagen. Nu skal jeg først lige få min computer til opføre sig pænt (Får nogle spøjse fejl når jeg compiler noget java kode. Den siger at der ikke findes nogle metode der hedder keys() i en HashMap??? Har prøvet med både blackdown linux j2sdk1.4.2 og sun's j2sdk1.5.0beta).
Avatar billede billen Nybegynder
03. april 2004 - 13:54 #11
(og ja, jeg ved godt der ikke er nogen keys() i HashMap, men det er slet ikke en hashmap jeg arbejder på, men en HashTable... meget mærkeligt)
Avatar billede billen Nybegynder
03. april 2004 - 21:02 #12
Jeg har prøvet dit eksempel (som minder utroligt meget om det jeg selv har prøvet, med undtagelse af at du starter med at få collection fra entiteten og ikke laver en ny collection).

Det duer ikke. Den opretter data i de enkelte entiteter men ikke i selve relationen. Og jeg får igen den der fejl jeg beskrev i spørgsmålet. Jeg vil lige prøve at ændre det til det du sagde. Hvad skal jeg gøre? Hvad betyder xa-datasource og hvor kan jeg læse om det jeg skal gøre?
Avatar billede billen Nybegynder
03. april 2004 - 21:03 #13
Jeg bruger også local interfaces hvis det nu kunne have en betydning!?!
Avatar billede arne_v Ekspert
03. april 2004 - 21:11 #14
Det forstår jeg ikke helt.

Jeg testede og checkede at der var blevet skrevet til M:M tabellen. Det var der.
Avatar billede arne_v Ekspert
03. april 2004 - 21:13 #15
Jeg testede også med en local-tx-datasource.

xa-datasource må være en XA compliant (supporterer 2PC) data source.
Avatar billede arne_v Ekspert
03. april 2004 - 21:14 #16
Har I oprettet i de 2 hoved tabeller - inden i I opretter i M:M tabellen ?
Avatar billede billen Nybegynder
03. april 2004 - 22:36 #17
Ja, det sker i denne rækkefølge:

- create File
- hent Collection fra File
- løkke
  - create Info
  - tilføj Info til Collection
- set Collection
Avatar billede billen Nybegynder
03. april 2004 - 22:37 #18
Og jeg skriver ud for hver eneste trin for at checke at der også sker det der skal ske, rent kodemæssigt.
Avatar billede arne_v Ekspert
03. april 2004 - 22:48 #19
Virker det hvis I ligesom i mit simple eksempel kun tilføjer eksisterende Info's
til File ?
Avatar billede arne_v Ekspert
03. april 2004 - 23:01 #20
Hvilken database ? Hvis jeg husker rigtigt at det er MySQL - MyISAM eller InnoDB
tabeller ? Hvis MS SQLServer eller MySQL med InnoDB tabeller - er der defineret
foreign key constraints ?
Avatar billede billen Nybegynder
03. april 2004 - 23:02 #21
Nej. Min procedure var åbenbart ikke detaljeret nok:

- create File
- hent Collection fra File
- løkke
  - kontroller om der findes en info med getByPrimaryKey()
    - Hvis ikke så create Info
  - tilføj Info til Collection
- set Collection
Avatar billede billen Nybegynder
03. april 2004 - 23:03 #22
Vi kører med MySQL med MyISAM (som ikke har foreign constraints).
Avatar billede arne_v Ekspert
03. april 2004 - 23:06 #23
Ingen fejl i loggen ?
Avatar billede billen Nybegynder
03. april 2004 - 23:07 #24
Ikke andet end

WARN  [TxConnectionManager] Prepare called on a local tx. Use of local transactions on a jta transaction with more than one branch may result in inconsistent data in some cases of failure.
Avatar billede arne_v Ekspert
03. april 2004 - 23:17 #25
Den fejl får jeg ikke. Et eller andet er forskelligt hos os.
Avatar billede arne_v Ekspert
03. april 2004 - 23:28 #27
OS, J2SE version og MySQL version bør være irrelevante.

Men jeg kører JBoss 3.2.3 (har 3.2.4 liggende klar til unzip). Måske betyder
det ord "beta" noget.  :-)

Jeg kigger på koden engang i morgen og ser om der er noget som
springer i øjnene.
Avatar billede billen Nybegynder
03. april 2004 - 23:30 #28
Det skal siges at vi helst vil køre jboss4, da den har en opgraderet version af AXIS, som tilbyder at overføre javabeans med hashtables(maps) og arrays tilknyttet.
Avatar billede billen Nybegynder
03. april 2004 - 23:30 #29
Men godnat og tak for forsøget indtil videre ;o)
Avatar billede billen Nybegynder
03. april 2004 - 23:39 #30
Det var også en JBoss4.0DR3 (developer release). Hvor har du egentlig 3.2.4 fra? er den ikke kun i RC1?
Avatar billede arne_v Ekspert
03. april 2004 - 23:51 #31
Ja - det er en RC1.
Avatar billede arne_v Ekspert
03. april 2004 - 23:52 #32
Så vidt jeg ved kan en normal Axis godt overføre maps, men det frarådes
fordi det kræver Java i begge ender.
Avatar billede arne_v Ekspert
04. april 2004 - 18:44 #33
Jeg hentede lige 4.0.0DR3 og testede med min kode.

Den virkede fint.
Avatar billede billen Nybegynder
04. april 2004 - 18:45 #34
Ja axis i jboss3 kan også overføre arrays, men ikke javabeans med arrays inden i.
Avatar billede arne_v Ekspert
04. april 2004 - 18:45 #35
Nu bruger I jo xdoclet. Hvordan er jeres deployment descriptorer kommet til at se ud ?
Avatar billede arne_v Ekspert
04. april 2004 - 18:47 #36
m.h.t. web service: er det ikke bare et spørgsmål om at angive serializer
i wsdd filen ?

(jeg har ikke prøvet med bean med aray men kun med array af bean)
Avatar billede billen Nybegynder
04. april 2004 - 18:49 #38
webservice: jo, men vi vil helst undgå at lave for meget special tilretning, så vi kan nøjes med at lade XDoclet generere vores kode.
Avatar billede arne_v Ekspert
04. april 2004 - 21:20 #39
Jeg kan godt forstå at I er gået på xdoclet - de filer er vokset til en pæn størrelse !
Avatar billede arne_v Ekspert
04. april 2004 - 21:33 #40
Nu har jeg kigget lidt.

Det eneste jeg har kunnet finde er:

    <ejb-relation>
      <ejb-relation-name>File-Info</ejb-relation-name>
      <relation-table-mapping>
        <table-name>fileinfo</table-name>
      </relation-table-mapping>
...

som jeg vill ehave forventet var.

    <ejb-relation>
      <ejb-relation-name>File-Info</ejb-relation-name>
      <relation-table-mapping>
        <table-name>fileinfo</table-name>
        <datasource>java:/OpenBroadDB</datasource>
        <datasource-mapping>mySQL</datasource-mapping>
  </relation-table-mapping>
...

Jeg ved ikke om det gør en forskel - og jeg ved ikke hvordan man får xdoclet til
at generere de 2 linier.
Avatar billede billen Nybegynder
04. april 2004 - 21:37 #41
Hmm du siger noget med den datasource der. Der er vist nok et xdoclet tag til lige præcis det. Prøver lige.
Avatar billede arne_v Ekspert
04. april 2004 - 21:42 #42
@jboss.relation-table har både datasource og datasource-mapping
Avatar billede billen Nybegynder
04. april 2004 - 21:43 #43
nemlig, lige ved at køre mit eksempel
Avatar billede billen Nybegynder
04. april 2004 - 21:44 #44
Nu genererer den de to tags. Nu må jeg se om det så virker.
Avatar billede billen Nybegynder
04. april 2004 - 21:48 #45
arne_v: Nu har du gjort det igen. Det virker f***** ;o) Læg et svar og få dine velfortjente point.
Avatar billede arne_v Ekspert
04. april 2004 - 21:49 #46
svar
Avatar billede arne_v Ekspert
04. april 2004 - 21:52 #47
Og hvis du undrer dig over hvorfor der ikke kom nogen fejl, så tror
jeg at JBoss har gemt relationerne - bare i den in memory HSQLDB database
som er default datasource.
Avatar billede billen Nybegynder
04. april 2004 - 21:56 #48
lol, det har den også.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester