# SQL Map File



## PollerJava (1. Okt 2007)

Hallo nochmal,  (neuer thread da das Tema jetzt eigentlich ein anderes ist)

ich bin gerade dabei, das SQL Map File zu machen, 
Ich frage mich gerade ob mein *.xml- file korrekt sein kann:


```
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="KW1_T1_Drehzahl">
	<select id="getDrehzahl" resultClass="net.datenbank.DBDriver">
		SELECT
			ZEITSTEMPEL 				as zeitstempel,
			WERT						as wert
                FROM #value#   // ist das hier möglich, den Namen als input anzugeben??????
			WHERE ZEITSTEMPEL BETWEEN = #value# AND #value#
	</select>	
</sqlMap>
```

Im Tutorial http://ibatis.apache.org/docs/java/pdf/iBATIS-SqlMaps-2-Tutorial_en.pdf  steht auf Seite 5:

"There is no way to specify the types of the output column" 

Das ist mir nicht ganz klar -> nur gewisse Zeilen anslesen wie ich es oben geschrieben habe (WHERE ZEITSTEMPEL BETWEEN = #value# AND #value#), geht aber schon, oder.

Und mir ist auch nicht ganz klar, wass ich hier:

```
<sqlMap namespace="hier ">
	<select id="hier" resultClass="und hier">
```

hinschreiben muss? Ist das wichtig für das DAO oder ist das nur eine User- Information?

lg und vielen Dank


----------



## maki (1. Okt 2007)

> hinschreiben muss? Ist das wichtig für das DAO oder ist das nur eine User- Information?


Wenn du ein Select statement hast, erwartest du doch einen Rückabewert, oder?

Das ist normalerweise ein Typ (Klasse), oder eine Hashmap.

Lies doch nochmal nach was ResultMaps sind


----------



## tuxedo (2. Okt 2007)

Also ich geh nochmal auf das Tutorial ein:


```
<sqlMap namespace="Person">

<select id="getPerson" parameterClass="int" resultClass="de.root1.cm.objects.Person">
SELECT
	id as id,
	firstName as firstName,
	lastName as lastName,
	birthDate as birthDate
FROM person
WHERE ID = #value#
</select>
...
```

Der Namespace gibt quasi an, was du mit dieser XML-File alles abdecken willst. Im Beispiel geht's ja um Personen die in der DB gespeichert sind. Hättest du noch "Hunde" in der DB und würdest die in deiner Anwendung benutzen wollen, hättest du wieder ne XML mit dem Namespace "Hund".

das mit _id="..."_:

Im Programmcode willst du ja auf die DB zugriefen, aber halt über iBatis. Und damit iBatis weiß was du mit der DB machen willst (neue Person einfügen, Person auslesen, Personen suchen, ....), musst du deinen Statements quasi Namen geben. Wenn du also ein Statement hast das eine Person in der DB selektiert, dann solltest du den id-Parameter auf irgendwas setzten was dem nahe kommt. z.B. "getPerson". Im Code wird dann  ja so drauf zugegriffen:


```
Integer personPk = new Integer(5);
Person person = (Person) sqlMap.queryForObject ("getPerson", personPk);
```

Du siehst: Hier wird bei "queryForObject" wieder die ID aus der XML angegeben. So weiß iBatis was du vor hast.

_resultClass _gibt an, in welche Klasse die aus der DB gelesenen Daten reingesteckt werden. 
Dabei st wichtig, dass in deinem SELECT Statement die Ergebnisspalten so heißen wie die Variablen in deiner _resultClass_ (ob man zwingend passende getter und setter brauch weiß ich jetzt nicht, aber ich vermute es mal).

Noch fragen?

[update]
Um auf deine Frage, ob das XML korrekt ist einzugehen: Nein, ist es nicht ;-) brauch noch nen kleinen Moment um das zu "korrigieren"....


----------



## tuxedo (2. Okt 2007)

Also, hab deinen Anwendungsfall mal etwas ausformuliert:


```
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="KW1_T1_Drehzahl">
   <select id="getZeitstempel" parameterClass="meinPackage.objekte.DrehzahlObjekt" resultClass="meinPackage.objekte.ZeitstempelObjekt">
      SELECT
         ZEITSTEMPEL             as zeitstempel,
         WERT                  as wert
                FROM #tabelle#   
         WHERE ZEITSTEMPEL BETWEEN = #wert1# AND #wert2#
   </select>   
</sqlMap>
```

Wenn du nicht nur eine Variable in das Statement einfügen willst, muss "parameterClass" die entsprechende Quelle der Variablen angeben. "resultClass" definiert die "Zielklasse" in der das Ergebnis gespeichert wird.


DrehzahlObjekt hat im inneren folgende Instanzvariablen (mit entsprechenden gettern und settern):
String tabelle;
int wert1;
int wert2;

ZeitstempelObjekt hat im inneren folgende Instanzvariablen (mit entsprechenden gettern und settern):
int zeitstempel;
int wert;

Die Abfrage in Java könnte dann wie folgt aussehen:

```
DrehzahlObjekt dzo = new DrehzahlObjekt();
dzo.setTabelle("meineDrehzahlTabelle");
dzo.setWert1(1234);
dzo.setWert2(4321);
List<ZeitstempelObjekt > zsoList = sqlMap.queryForList("getZeitstempel", dzo);
```

Da vermutlich mehrere Einträge in der Tabelle auf die Abfrage zutreffen, wird das Ergebnis ein eine "ZeitstempelObjekt"-Liste gesichert. Dasd kannst du dann mit 


```
for (ZeitstempelObjekt zso: zsoList ) {
			System.out.println(zso.getZeitstempel()+" - "+zso.getWert());
		}
```

durchlaufen....

Hab das eben mal kurz "zusammengeschmiert", ist also nicht gesagt dass das Fehlerfrei funktioniert. Jedefalls zeigt es schonmal das genauere Prinzip auf...

- Alex


----------



## PollerJava (2. Okt 2007)

Hallo nochmal,

ich bin am nachvollziehen des Tutorials- Beispieles und habs fast (auch verstanden-> danke für die erklärungen!!),
Mein Problem ist noch diese Fehlermeldung:


```
Exception in thread "main" org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544344. I/O error for file %.0s"CreateFile (open)"
null
Error while trying to open file
null
Reason: I/O error for file %.0s"CreateFile (open)"
null
Error while trying to open file
null
        at org.firebirdsql.jdbc.FBDataSource.getConnection(FBDataSource.java:122)
        at org.firebirdsql.jdbc.FBDriver.connect(FBDriver.java:131)
        at java.sql.DriverManager.getConnection(DriverManager.java:582)
        at java.sql.DriverManager.getConnection(DriverManager.java:185)
        at com.ibatis.common.jdbc.SimpleDataSource.popConnection(SimpleDataSource.java:571)

usw...
```

was stimmt da noch nicht, habt ihr da eine Ahnung,


lg und Danke


----------



## tuxedo (2. Okt 2007)

Naja, da steht doch alles... Firebird kann die Datei mit dem Namen "%.0s"" nicht öffnen. 

Zeig mal 

a) wie die XML-SQL-Map aussieht
b) wie der Aufruf im Java-Code aussieht und wie die Variablen aussehen die du da reinsteckst.

- Alex


----------



## maki (2. Okt 2007)

Das steht, das es einen Fehler gab, als der Treiber eine Connection erstelen wollte.

Was steht denn in deiner sql-map-config?


----------



## PollerJava (2. Okt 2007)

Meine Dateien schauen so aus:

Meine SQLMApConfigExample.xml:

```
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
<properties resource="sqlTest/DBXML/SqlMapConfigExample.properties" />
	<settings
		cacheModelsEnabled="true"
		enhancementEnabled="true"
		lazyLoadingEnabled="true"
		maxRequests="32"
		maxSessions="10"
		maxTransactions="5"
		useStatementNamespaces="false"
	/>
	<typeAlias alias="order" type="testdomain.Order"/>

	<transactionManager type="JDBC" >
		<dataSource type="SIMPLE">
			<property name="JDBC.Driver" value="${driver}"/>
			<property name="JDBC.ConnectionURL" value="${url}"/>
			<property name="JDBC.Username" value="${username}"/>
			<property name="JDBC.Password" value="${password}"/>
		</dataSource>
	</transactionManager>
<sqlMap resource="sqlTest/DBXML/Person.xml" />
</sqlMapConfig>
```


Meine *.properties- Datei

```
driver=org.firebirdsql.jdbc.FBDriver
url=jdbc:firebirdsql:localhost:c:\Projekte\PERSON.FDB
username=SYSDBA
password=masterkey
```

Meine Person.xml

```
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Person">

<select id="getPerson" parameterClass="int" resultClass="sqltest.Person">
	SELECT
	PER_ID as id,
	PER_FIRST_NAME as firstName,
	PER_LAST_NAME as lastName,
	PER_BIRTH_DATE as birthDate,
	PER_WEIGHT_KG as weightInKilograms,
	PER_HEIGHT_M as heightInMeters
	FROM PERSON
	WHERE PER_ID = #value#
</select>

<insert id="insertPerson" parameterClass="sqltest.Person">
	INSERT INTO PERSON (PER_ID, PER_FIRST_NAME, PER_LAST_NAME, 
						PER_BIRTH_DATE, PER_WEIGHT_KG, PER_HEIGHT_M) 
	VALUES (#id#, #firstName#, #lastName#, 
			#birthDate#, #weightInKilograms#, #heightInMeters#)
</insert>

<update id="updatePerson" parameterClass="sqltest.Person">
	UPDATE PERSON
	SET PER_FIRST_NAME = #firstName#,
	PER_LAST_NAME = #lastName#, PER_BIRTH_DATE = #birthDate#,
	PER_WEIGHT_KG = #weightInKilograms#,
	PER_HEIGHT_M = #heightInMeters#
	WHERE PER_ID = #id#
</update>

<delete id="deletePerson" parameterClass="sqltest.Person">
	DELETE PERSON
	WHERE PER_ID = #id#
</delete>
</sqlMap>
```

In test.java

```
public class Test 
    {
    
   
    public Test() 
        {
        }  
    
    public static void main(String[] args) throws SQLException
        {
        SqlMapClient sqlMap = MyAppSqlConfig.getSqlMapInstance();
       
        Person person1 = new Person();
        person1.setId(1);
        person1.setFirstName("");
        person1.setLastName("");
        person1.setBirthDate(null);
        person1.setHeightInMeters((float)12.4);
        person1.setWeightInKilograms((float)85.5);       
        sqlMap.insert("insertPerson", person1);
        
 
        
        Integer personPk = new Integer(1);        
        Person person = (Person)sqlMap.queryForObject("getPerson", personPk); 
        //System.out.println("Das ist die Person: " + person.getFirstName() + ", " + person.getLastName());
        }
    }
```


mein Person.java


```
public class Person 
    {
    private int id;
    private String firstName;
    private String lastName;
    private Timestamp birthDate;
    private float weightInKilograms;
    private float heightInMeters;
    
    public Person() 
        {
        }
       
    public void setId(int id)
        {
        this.id = id;
        }
    
    public int getId()
        {
        return id;
        }
    
    public void setFirstName(String firstName)
        {
        this.firstName = firstName;
        }
    
    public String getFirstName()
        {
        return firstName;
        }
    
    public void setLastName(String lastName)
        {
        this.lastName = lastName;
        }
    
    
    public String getLastName()
        {
        return lastName;
        }
    
    public void setBirthDate(Timestamp birthDate)
        {
        this.birthDate = birthDate;
        }
    
    public Timestamp getBirthDate()
        {
        return birthDate;
        }
    
    public void setWeightInKilograms(float weightInKilograms)
        {
        this.weightInKilograms = weightInKilograms;
        }
    
    public float getWeightInKilograms()
        {
        return weightInKilograms;
        }
    
    public void setHeightInMeters(float heightInMeters)
        {
        this.heightInMeters = heightInMeters;
        }
    
    public float getHeightInMeters()
        {
        return heightInMeters;
        }
    }
```


----------



## tuxedo (2. Okt 2007)

In deiner Properties hast du \ statt / (oder \\) in der URL benutzt. 
\ ist Windows-Stil... Aber platformübergreifend wird eigentlich / benutzt.
Versuch das mal zu ändern. Am besten:

url=jdbc:firebirdsql:localhost:c:/Projekte/PERSON.FDB 

Glaub aber nicht dass das der alleinige Fehler war. Aber vielleicht irre ich mich ja.

- Alex


----------



## maki (2. Okt 2007)

Der backslash ist ein sonderzeichen welches maskiert werden muss:


```
jdbc:firebirdsql:localhost:c:\\Projekte\\PERSON.FDB
```


----------



## tuxedo (2. Okt 2007)

[joke]maki ist heute mein persönlicher Papagei[/joke] ;-)


----------



## maki (2. Okt 2007)

dacht ich mir auch schon lol

naja, dann ist es wohl zeit für mich, den schnabel zu halten *g*

_note to myself: stfu!_


----------



## tuxedo (2. Okt 2007)

Ich vermute mal es liegt wieder an der Sache mit der fehlenden Info vor dem "senden" Button: "Achtung: MIttlerweile wurde ein weiterer Beitrag verfasst. Eigenen neuen Beitrag wirklich absenden?" ...

Aber wie heisst's doch so schön: Doppelt hält besser ;-)

- Alex


----------



## PollerJava (2. Okt 2007)

Unglaublich aber war, ich hab das Beispiel (halb) vom Tutorial,

ich kann aus der DB auslesen und mir ist das meiste auch klar, nur beim "insert" bekomme ich noch einen Fehler und weiß nicht genau, wo ich nach dem Fehler suchen soll,
In der Person.xml steht alles genauso drinnen wie im Tutorial,

Vielen Dank für Eure Hilfe


```
Exception in thread "main" com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred in sqlTest/DBXML/Person.xml.  
--- The error occurred while applying a parameter map.  
--- Check the insertPerson-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544665. violation of PRIMARY or UNIQUE KEY constraint "INTEG_6" on table "PERSON"
Caused by: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544665. violation of PRIMARY or UNIQUE KEY constraint "INTEG_6" on table "PERSON"
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate(GeneralStatement.java:91)
        at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.insert(SqlMapExecutorDelegate.java:442)
        at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.insert(SqlMapSessionImpl.java:81)
        at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.insert(SqlMapClientImpl.java:58)
        at sqltest.Test.main(Test.java:27)
Caused by: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544665. violation of PRIMARY or UNIQUE KEY constraint "INTEG_6" on table "PERSON"
        at org.firebirdsql.jdbc.AbstractPreparedStatement.internalExecute(AbstractPreparedStatement.java:712)
        at org.firebirdsql.jdbc.AbstractPreparedStatement.execute(AbstractPreparedStatement.java:645)
        at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate(SqlExecutor.java:84)
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteUpdate(GeneralStatement.java:200)
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate(GeneralStatement.java:78)
        ... 4 more

Caused by: 
org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544665. violation of PRIMARY or UNIQUE KEY constraint "INTEG_6" on table "PERSON"
        at org.firebirdsql.jdbc.AbstractPreparedStatement.internalExecute(AbstractPreparedStatement.java:712)
        at org.firebirdsql.jdbc.AbstractPreparedStatement.execute(
```


----------



## tuxedo (2. Okt 2007)

Ganz einfach: In der Fehlermeldung taucht doch immer wieder "violation of PRIMARY or UNIQUE KEY constraint" auf...

D.h. du versucht immer und immer wieder ein und dieselbe Person (sprich: ein und dieselbe Personen-ID) in die DB einzutragen. 

Die ID-Spalte der Person in der Tabelle machst du am besten auf Auto-Increment und lässt den ID-Wert im Personenobjekt leer. Entsprechend sollte auch das einfügen der Personen-ID in der XML wegfallen.

Also:


```
<insert id="insertPerson" parameterClass="sqltest.Person">
   INSERT INTO PERSON (PER_FIRST_NAME, PER_LAST_NAME,
                  PER_BIRTH_DATE, PER_WEIGHT_KG, PER_HEIGHT_M)
   VALUES (#firstName#, #lastName#,
         #birthDate#, #weightInKilograms#, #heightInMeters#)
</insert>
```


und


```
Person person1 = new Person();
//        person1.setId(1);
        person1.setFirstName("Max");
        person1.setLastName("Quehen");
        person1.setBirthDate(null);
        person1.setHeightInMeters((float)12.4);
        person1.setWeightInKilograms((float)85.5);       
        sqlMap.insert("insertPerson", person1);
```

Wobei... Wenn du in der XML schon die Sache mit der Personen-ID weggelassen hast, dann ist es eigentlich "egal" ob du im Personen-Objekt die ID setzt oder nicht, weil iBatis verwendet die ID dann einfach nicht (schließlich hast du sie in der XML ab sofort weggelassen).

Musst halt nur noch drauf achten die ID-Spalte auf auto-increment zu setzen.

- Alex


----------



## PollerJava (2. Okt 2007)

Alles klar, ich habs, kann natürlich den Priary Key nicht 2 mal eintragen!!!


Vielen Dank für EURE HILFE!!!!

lg


----------



## PollerJava (2. Okt 2007)

alex0801 hat gesagt.:
			
		

> Ich vermute mal es liegt wieder an der Sache mit der fehlenden Info vor dem "senden" Button: "Achtung: MIttlerweile wurde ein weiterer Beitrag verfasst. Eigenen neuen Beitrag wirklich absenden?" ...
> 
> Aber wie heisst's doch so schön: Doppelt hält besser ;-)
> 
> - Alex




Das wäre jetzt auch notwendig gewesen, war leider zu langsam,

lg und DANKE!!


----------



## PollerJava (2. Okt 2007)

Hab jetzt deinen Beitrag nochmal gelesen, das werd ich dann bei meinen Leistungen  usw auch so machen,


----------



## tuxedo (2. Okt 2007)

Naja, jetzt kannst du's krachen lassen. Bist ja jetzt bestens Ausgerüstet mit Wissen und Werkzeug ;-)

-Alex


----------



## maki (2. Okt 2007)

Soll ich Alex'Post abwarten? *g*

Das liegt an deiner DB, 


```
violation of PRIMARY or UNIQUE KEY constraint "INTEG_6" on table "PERSON"
```
tja, was ist den der contraint integ_6?

Ein Fremdschlüssel, den du falsch befüllst?
Oder etwa ein feld das eindeutig sein muss, welches du aber in 2 Datensätzen mit demselben wert ablegen willst?

Nebenbei bemerkt, du solltest das logging einschalten, dass du auch siehst was passiert, im Manual steht drinnen wie das geht.
Kennst du dich mit log4j aus?


----------



## PollerJava (2. Okt 2007)

Noch nie verwendet aber schon óft daran gedacht, ich programmiere mom. in NetBeans, wenn mein Programm aber dann jemand anders mit einer * bat- Datei ausführt, weiß ich ja nicht mehr, was für Fehlermeldungen daherkommen, daher steht mir log4j noch bevor,


----------



## tuxedo (2. Okt 2007)

@maki:

Wieder zu langsam ;-) LOL Scroll' mal an's Ende von Seite 1 ...

- Alex


----------



## maki (2. Okt 2007)

alex0801 hat gesagt.:
			
		

> @maki:
> 
> Wieder zu langsam ;-) LOL Scroll' mal an's Ende von Seite 1 ...
> 
> - Alex


Schon  gesehen, aber wiedermal zu spät... ist gerade Oktoberfestzeit in München, und ich muss heute schon wieder hin... alles beruflich versteht sich 

log4j ist imho zur Zeit die beste Wahl zum loggen.

Das gibts auch gute tutorials zu, es ist eigentlich sehr trivial aber sehr mächtig.


----------



## PollerJava (2. Okt 2007)

ja nach dem DAO werd ich mich dann log4j widmen, Ich befürchte fürs Forum, das ich dieses wieder Strapazieren muss,

lg und Brost


----------



## PollerJava (2. Okt 2007)

Hallo nochmal,

ich habe jetzt versucht, anders auszulesen, da ich das für mein Projekt benötige, bekomme aber die untere Fehlermeldung, da ich jetzt ein Objekt  in der Methode qlMap.queryForObject("getPerson", ro); übergebe und nicht mehr einen Integer,

Was mache ich da falsch, der Methode qlMap.queryForObject("getPerson", ro);  kann man ja ein Objekt übergeben, das geht ja aber das DAO mag das irgendwie nicht,

lg


```
<select id="getPerson" parameterClass="int" resultClass="sqltest.Person">
	SELECT
		PER_ID 			as id,
		PER_FIRST_NAME 	as firstName,
		PER_LAST_NAME 	as lastName,
		PER_BIRTH_DATE 	as birthDate,
		PER_WEIGHT_KG 	as weightInKilograms,
		PER_HEIGHT_M 	as heightInMeters
	FROM #PERSON#                                                   // hier auch den Tabellennamen übergeben
	WHERE PER_ID = #value#
</select>
```


```
ReadObj ro = new ReadObj();
        ro.setId(11);
        ro.setTabelle("PERSON");
        Person person = new Person();
        person.setTabelle("Person");
        person.setId(11);
        person = (Person)sqlMap.queryForObject("getPerson", ro);
```



```
public class ReadObj 
    {
    private String tabelle;
    private int id;
    
    public ReadObj() 
        {
        }
    
    public void setTabelle(String tabelle)
        {
        this.tabelle = tabelle;
        }
    
    public String getTabelle()
        {
        return tabelle;
        }
    
    public void setId(int id)
        {
        this.id = id;
        }
    
    public int getId()
        {
        return id;
        }
    }
```


bekomme aber folgende Fehlermeldung:


```
Exception in thread "main" com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred in sqlTest/DBXML/Person.xml.  
--- The error occurred while preparing the mapped statement for execution.  
--- Check the getPerson.  
--- Cause: java.sql.SQLException: Invalid parameter object type.  Expected 'java.lang.Integer' but found 'sqltest.ReadObj'.
Caused by: java.sql.SQLException: Invalid parameter object type.  Expected 'java.lang.Integer' but found 'sqltest.ReadObj'.
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:185)
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:104)
        at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:561)
        at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:536)
        at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:93)
        at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:70)
        at sqltest.Test.main(Test.java:39)
Caused by: java.sql.SQLException: Invalid parameter object type.  Expected 'java.lang.Integer' but found 'sqltest.ReadObj'.
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.validateParameter(GeneralStatement.java:229)
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:151)
        ... 6 more
```


----------



## maki (2. Okt 2007)

```
parameterClass="int"
```
... und du möchtest ein sog. ReadObj übergeben, das geht natürlich nicht.

Edit: Ich sehe übrigens nicht, wo du DAOs einsetzt, nur SqlMaps  ???:L


----------



## PollerJava (2. Okt 2007)

Ja SQL Maps,

Wie kann ich das dann machen, dass ich ein Objekt übergebe, in welchem drinnensteht aus welcher Tabelle in der DB auszulesen ist?

z.B.: wenn ich die Tabellen 
Person
Ausserirdische
Tiere

habe, dass ich den tabellennamen und die id setze:


```
ReadObj ro = new ReadObj();
  ro.setId(11);
  ro.setTabelle("Tiere");
person = (Person)sqlMap.queryForObject("getPerson", ro);
```

und dann eben aus Tier die id 11 bekomme?

geht das irgendwie??

lg


----------



## tuxedo (2. Okt 2007)

Fehler ist einfach, du siehst nur den Wald vor lauter Bäumen nicht mehr:


```
<select id="getPerson" parameterClass="int" resultClass="sqltest.Person">
   SELECT
      PER_ID          as id,
      PER_FIRST_NAME    as firstName,
      PER_LAST_NAME    as lastName,
      PER_BIRTH_DATE    as birthDate,
      PER_WEIGHT_KG    as weightInKilograms,
      PER_HEIGHT_M    as heightInMeters
   FROM #PERSON#                                                   // hier auch den Tabellennamen übergeben
   WHERE PER_ID = #value#
</select>
```

Wenn du mehrere Werte im Statement verwendest, solltest du unter "parameterClass" auch das richtige angeben. 
Wenn die Werte im ReadObject "ro" stehen, sollte dein XML so aussehen:


```
<select id="getPerson" parameterClass="sqltest.ReadObj" resultClass="sqltest.Person">
   SELECT
      PER_ID          as id,
      PER_FIRST_NAME    as firstName,
      PER_LAST_NAME    as lastName,
      PER_BIRTH_DATE    as birthDate,
      PER_WEIGHT_KG    as weightInKilograms,
      PER_HEIGHT_M    as heightInMeters
   FROM #tabelle#                                                   // hier auch den Tabellennamen übergeben
   WHERE PER_ID = #id#
</select>
```

Habs nicht getestet, sollte aber gehen.

@maki

Bin in iBatis auch noch nicht sooo weit drin. Aber was sind denn DAO's? Laut Wikipedia ist DAO ein Entwurfsmuster. Also eine Art und Weise etwas zu bewerkstelligen.

- Alex


----------



## PollerJava (2. Okt 2007)

Da bekomme ich folgende Fehlermeldung:


```
com.ibatis.common.exception.NestedRuntimeException: Error occurred.  Cause: com.ibatis.common.xml.NodeletException: Error parsing XML.  Cause: com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMapConfig/sqlMap'.  Cause: com.ibatis.common.xml.NodeletException: Error parsing XML.  Cause: com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMap/select'.  Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMap/select'.  Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.xml.NodeletException: Error parsing XML.  Cause: com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMap/select'.  Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMap/select'.  Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMapConfig/sqlMap'.  Cause: com.ibatis.common.xml.NodeletException: Error parsing XML.  Cause: com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMap/select'.  Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
Caused by: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
```

was muss ich den da in meine Klass ReadObj noch reinpacken,

eigentlich hab ich mir das so gedacht, dass ReadObj dazu da ist, die parameterClass zu setzen und das ergebnis dann n person steht aber leider eben folgende obere Fehlermeldung,


----------



## maki (2. Okt 2007)

> Wie kann ich das dann machen, dass ich ein Objekt übergebe, in welchem drinnensteht aus welcher Tabelle in der DB auszulesen ist?


Das hast du doch schon gemacht, indem du den Tabellennamen als Parameter hernimmst, wovon dir übrigens gestern abgeraten wurde, in deinem anderen Thread ("Kennst du die Tabellen schon wenn du kompilierst?"), da es sich um ein ziemlich "seltsames" Design handelt.

Jetzt müsstest du noch einsehen, dass du deine parameterclass anpassen musst, so wie es auch in der doku steht.
Wenn du int als parameter angibst, aber ein ReadObj übergibst, ist doch etwas faul oder?


----------



## PollerJava (2. Okt 2007)

Ja das habe ich ja schon gemacht:


```
<select id="getPerson" parameterClass="sqltest.ReadObj" resultClass="sqltest.Person">   
	SELECT
		PER_ID 			as id,
		PER_FIRST_NAME 	as firstName,
		PER_LAST_NAME 	as lastName,
		PER_BIRTH_DATE 	as birthDate,
		PER_WEIGHT_KG 	as weightInKilograms,
		PER_HEIGHT_M 	as heightInMeters
	FROM #PERSON#
	WHERE PER_ID = #value#
</select>
```

Da bekomme ich eben die Fehlermeldung von oben,


----------



## tuxedo (2. Okt 2007)

Du hast meinen Beitrag also gekonnt ignoriert oder wie? --> Lesen

[update]

Für dich nochmal:


```
<select id="getPerson" parameterClass="sqltest.ReadObj" resultClass="sqltest.Person">
   SELECT
      PER_ID          as id,
      PER_FIRST_NAME    as firstName,
      PER_LAST_NAME    as lastName,
      PER_BIRTH_DATE    as birthDate,
      PER_WEIGHT_KG    as weightInKilograms,
      PER_HEIGHT_M    as heightInMeters
   FROM #tabelle#                                                   // hier auch den Tabellennamen übergeben
   WHERE PER_ID = #id#
</select>
```

btw: die Fehlermeldung passt nicht zu deiner XML... Laut fehlermeldung hast du im XML irgendwo #person# verwendet .. Aber das ist in deinen Ausführungen nicht ersichtlich ....

Und wie maki schon sagte: Es zeugt von einem schlechten DB-Design wenn man den Namen der Tabelle in einem Statement mit einer Variablen setzt.

- Alex


----------



## PollerJava (2. Okt 2007)

Genau so hab ichs ja:


```
<select id="getPerson" parameterClass="sqltest.ReadObj" resultClass="sqltest.Person">   
	SELECT
		PER_ID 			as id,
		PER_FIRST_NAME 	as firstName,
		PER_LAST_NAME 	as lastName,
		PER_BIRTH_DATE 	as birthDate,
		PER_WEIGHT_KG 	as weightInKilograms,
		PER_HEIGHT_M 	as heightInMeters
	FROM #PERSON#
	WHERE PER_ID = #value#
</select>
```


und da bekomme ich eben die Fehlermeldung:


```
com.ibatis.common.exception.NestedRuntimeException: Error occurred.  Cause: 
com.ibatis.common.xml.NodeletException: Error parsing XML.  Cause: 
com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMapConfig/sqlMap'.  Cause: 
com.ibatis.common.xml.NodeletException: Error parsing XML.  Cause: 
com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMap/select'.  Cause: 
com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'



Caused by: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'

Caused by: com.ibatis.common.exception.NestedRuntimeException: Error parsing XPath '/sqlMap/select'.  Cause: 
com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'

Caused by: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'PERSON' in class 
'sqltest.ReadObj'
```
[/code]


Mein Ziel ist es ja, das was du mir geschrieben hast nachzustellen mit den Personen:


```
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="KW1_T1_Drehzahl">
   <select id="getZeitstempel" parameterClass="meinPackage.objekte.DrehzahlObjekt" resultClass="meinPackage.objekte.ZeitstempelObjekt">
      SELECT
         ZEITSTEMPEL             as zeitstempel,
         WERT                  as wert
                FROM #tabelle#   
         WHERE ZEITSTEMPEL BETWEEN = #wert1# AND #wert2#
   </select>   
</sqlMap>
```


```
DrehzahlObjekt dzo = new DrehzahlObjekt();
dzo.setTabelle("meineDrehzahlTabelle");
dzo.setWert1(1234);
dzo.setWert2(4321);
List<ZeitstempelObjekt > zsoList = sqlMap.queryForList("getZeitstempel", dzo);
```


----------



## maki (2. Okt 2007)

PollerJava, 

du magst aber deine Fehlermeldungen schon noch selbst auch lesen, oder überlässt du uns jetzt alles?


```
There is no READABLE property named 'PERSON' in class 'sqltest.ReadObj'
```
Na was könnte das wohl bedeuten?





> Aber was sind denn DAO's? Laut Wikipedia ist DAO ein Entwurfsmuster. Also eine Art und Weise etwas zu bewerkstelligen.


Es gibt verschiedene Arten von Mustern, DAO ist ein Architektur Muster, das gibt's auch in anderen Programmiersprachen.

http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html

Man beachte die Klassenhierarchie. 

AbstractFactory erzeugt AbstractProduct
ConcreteFactory erzeugt ConcreteProduct

Über die AbstractFactory bekomm ich eine ConcreteFactory.

Man kann sich die AbstractFactory sparen, wenn man nur eine DB 
verwendet.

aufgerufen wird es dann so ähnlich im Quellcode, nur mit konkreten factories und products (my...):

```
MyDao myDao = DAOFactory.getFactory().getMyDAO();
```
Nun hat man ein DataAccessObject, ein Objekt, dass denn zugriff auf Datenbanken kapselt, ob dahinter iBatis oder Hibernate oder sonstwas steckt, weiss man nicht, und das ist gut so 

Man benutzt einfach die Methoden, welche das DAO zur verfügung stellt, zB.:

```
myDao.save( myObject );
```


----------



## PollerJava (2. Okt 2007)

Die Erklärung von DAO geht aber nicht an mich, oder? (ich glaucbe es hat ja Alex gefragt)

Es tut mir echt leid, das ich mich so anstelle, aber ich weiß nicht, was ich in ReadObj noch reinschreiben muss, damit es funktioniert:


```
public class ReadObj 
    {
    private String tabelle;
    private int id;
    
    public ReadObj() 
        {
        }
    
    public void setTabelle(String tabelle)
        {
        this.tabelle = tabelle;
        }
    
    public String getTabelle()
        {
        return tabelle;
        }
    
    public void setId(int id)
        {
        this.id = id;
        }
    
    public int getId()
        {
        return id;
        }
    }
```

Mit 
	
	
	
	





```
private Person person;

und den getter und setter- Methoden für Person habe ich es schon versucht, das ist es auf jeden Fall nicht
```


----------



## PollerJava (2. Okt 2007)

Ich habs schon, es ist besser, wenn ich heute es für heute lassen würde, halleluja,
Danke für die geduld


----------



## tuxedo (2. Okt 2007)

Um die Verwirrung zu komplettieren:

@PollerJava

du hast in deiner XML folgendes stehen:
WHERE PER_ID = #value# 

Und bei mir stand da:
WHERE PER_ID = #id# 

Woher allerdings das Problem mit "Person" kam ist nach wie vor ein Rätsel. Jedenfalls hats iBatis nicht gepasst.

@Maki

Naja, wenn ich dich richtig verstanden habe ist DAO noch eine Stufe abstrakter. In wieweit iBatis da ein Konstrukt zur verfügung stellt: Kein Plan, hab ich mich drum gekümmert.

Aber ich denke wer anständige Software schreibt der macht's eh Plug'n'Play so dass verschiedene Schichten austauschbar sind. Bei mir wäre das z.B. in der Serverschicht wo ich eine Persistenz-Klasse hab der ich, wie du schon geschrieben hattest sagen kann:  savePerson(personA); und der Rest "geht mich  nix mehr an". Via Interfaces lässt sich diese Schicht ja beliebig tauschen. Ob dann iBatis dahinter arbeitet oder ob ein "manisch depressiver Roboter" (Ich liebe Douglas Adams ;-) ) für die Persistenz zuständig ist, ist dann ja schnuppe.
ich glaub ich habs jetzt begriffen. Im Prinzip war mir's schon die ganze Zeit klar, nur hatte ich es unter nem anderen Namen im Hirn gespeichert.

- Alex

P.S. @Poller

Könntest du deinen ewig breiten Post bitte in der Zeile unbrechen? Das packt selbst meine 1680x1050 Auflösung nicht...


----------



## PollerJava (2. Okt 2007)

Einmal muss ich euch noch fragen:

Ich habs jetzt so wie unten, wenn ich statt #tabelle# -> PERSON hinschreibe, dann funktionierts super nur wenn ich den Namen der tabelle mit #tabelle# angeben will, dann bekomme ich wieder mal einen Fehler -> er mag das SQL Statement nicht, was kann ich da machen??




```
<select id="getPerson" parameterClass="sqltest.ReadObj" resultClass="sqltest.Person">   
	SELECT
		PER_ID 			as id,
		PER_FIRST_NAME 	as firstName,
		PER_LAST_NAME 	as lastName,
		PER_BIRTH_DATE 	as birthDate,
		PER_WEIGHT_KG 	as weightInKilograms,
		PER_HEIGHT_M 	as heightInMeters
	FROM #tabelle#
	WHERE PER_ID = #id#
</select>
```




```
Exception in thread "main" com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred in sqlTest/DBXML/Person.xml.  
--- The error occurred while executing query.  
--- Check the     	SELECT 		PER_ID 			as id, 		PER_FIRST_NAME 	as firstName, 
	PER_LAST_NAME 	as lastName, 		PER_BIRTH_DATE 	as birthDate, 		PER_WEIGHT_KG 	as 
weightInKilograms, 		PER_HEIGHT_M 	as heightInMeters 	FROM ? 	WHERE PER_ID = ? .  
--- Check the SQL Statement (preparation failed).  
--- Cause: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544569. Dynamic SQL Error
SQL error code = -104
Token unknown - line 1, column 205
```


Kann es sein, dass man den Tabellennamen nicht angeben kann???

Ich befürchte schlimmes


----------



## tuxedo (2. Okt 2007)

Ich sags nur ungern mehrfach:

a) Kümmer dich bitte um ein anständiges DB-Design.. Das was du da machst ist wie "Kraut und Rüben". Das ist mindestens genauso "uncool" wie den kompletten Java-Code einer 2500 Zeilen Klasse in eine einzige Zeile zu tippen.
b) Sei so gut und brich endlich diese endlos lange Zeile um. Nicht jeder hat hier nen 200:10 Monitor (16:10 reicht ja bei weiten nicht aus..)

Und zu deinem Problem:

Wenn du #person# statt #tabelle# machst funktioniert's ??? Tja, dürfte es aber nicht. Wenn doch ist deine parameterClass nicht so wie sie sein soll. Nichts desto trotz, siehe a) !!!

- Alex


----------



## tuxedo (2. Okt 2007)

So langsam verstehe ich...

Es ist schon klar dass es funktioniert wenn du statt "#tabelle#" -> "PERSON" hinschreibst. Denn ersteres ist eine Variable, letzteres eine feste Definition für das SELECT Statement dass es in der PERSON Tabelle nachsieht. 

Ändert aber nix an der Tatsache von a) aus dem letzten Post.

- Alex


----------



## PollerJava (3. Okt 2007)

alex0801 hat gesagt.:
			
		

> Ich sags nur ungern mehrfach:
> 
> a) Kümmer dich bitte um ein anständiges DB-Design.. Das was du da machst ist wie "Kraut und Rüben". Das ist mindestens genauso "uncool" wie den kompletten Java-Code einer 2500 Zeilen Klasse in eine einzige Zeile zu tippen.
> - Alex



Ich versteh dann deinen Vorschlag von unten nicht, da wird ja auch der Tabellenname ausgegenen von welcher ich auslesen möchte und das funktioniert eben nicht, ich kann nur statt #tabelle# eben den fixen Namen hinschreiben -> dann funktionierts aber keinen Tabellennamen übergeben -> das geht nicht!!!


```
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="KW1_T1_Drehzahl">
   <select id="getZeitstempel" parameterClass="meinPackage.objekte.DrehzahlObjekt" resultClass="meinPackage.objekte.ZeitstempelObjekt">
      SELECT
         ZEITSTEMPEL             as zeitstempel,
         WERT                  as wert
                FROM #tabelle#   
         WHERE ZEITSTEMPEL BETWEEN = #wert1# AND #wert2#
   </select>   
</sqlMap>
```


----------

