# SQLData



## Wepa (17. Mrz 2012)

Guten Tag,

ich möchte in einen eigen erstellten Datenbanktypen in einen Javatypen umwandeln um bequem mit den getObject und setObject Metoden von eine ResultSet arbeiten zu können. Dabei wollte ich wie folgt vorgehen:


```
CREATE TYPE person
(
   name VARCHAR(50),
   age INT
)
```


```
public class Person implements SQLData 
{
   public String name;
   public int age;
   
   public String getSQLTypeName() 
   {
      return "person";
   }

   public void readSQL(SQLInput stream, String type) throws SQLException 
   {
      name = stream.readString();
      age = stream.readInt();
   }

   public void writeSQL(SQLOutput stream) throws SQLException 
   {
      stream.writeString(name);
      stream.writeInt(age);
   }
}
```

Leider scheitert es schon beim erstellen des Typen *person*. Momentan  benutze ich *h2* als DBMS, wobei diese anscheinend keine benutzerdefinierte Typen unterstützt.Meine Frage lautet: Welche in Java geschriebenes DBMS kann dieses oder welche anderen wege gibt es um Javatypen in Datenbanktypen abzubilden?

mfg Wepa


----------



## turtle (18. Mrz 2012)

Eigentlich sollte jeder O/R-Mapper von SQL-Datentypen auf Java-Datentypen mappen können.

Beliebte Mapper sind derzeit Hibernate, JPA oder mein häufig eingesetztes myBATIS.

Dein Beispiel macht sich des objekt-relationalen Mappings in der Datenbank zu Nutze. Dieses ist aber sehr von der DB abhängig und wird (daher) meines Wissens selten eingesetzt. 

Ich rate Dir daher auf eine "normale" SQL-DB aufzusetzen und mit einem O/R-Mapper Deiner Wahl in Java weiterzumachen. Wenn Du gut SQL kennst und vielleicht schon die DB vorliegen hast, rate ich zu myBATIS, sonst JPA.


----------



## Wepa (20. Mrz 2012)

Danke für den Tipp turtle. MyBatis ist genau das, was ich gesucht habe, aber ich bekomme es nicht zum laufen.

*db.properties*

```
dbDriver=org.apache.derby.jdbc.EmbeddedDriver
dbUrl=jdbc:derby:testdb
dbUser=root
dbPassword=root
```

*Person.xml*

```
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="Person">
    <select id="selectAllPersons" resultType="Person">
        select id,vorname,nachname from person
    </select>
</mapper>
```
*
SqlMapConfig.xml*
[XML]<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="database/db.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${dbDriver}" />
                <property name="url" value="${dbUrl}" />
                <property name="username" value="${dbUser}" />
                <property name="password" value="${dbPassword}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="database/Person.xml" />
    </mappers>
</configuration>[/XML]


```
public static void main(String[] args)
	{
		MAIN.erstelleDB();
		try
		{

			System.out.println(new File("database/SqlMapConfig.xml").exists());
			System.out.println(new File("database/Person.xml").exists());
			System.out.println(new File("database/db.properties").exists());
			
			Reader reader = Resources.getResourceAsReader("database/SqlMapConfig.xml");
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
			SqlSession sqlSession = sqlSessionFactory.openSession();
			try
			{
				@SuppressWarnings("unchecked")
				List<Person> listPersons = sqlSession.selectList("Person.selectAllPersons");
				for (Person person : listPersons)
				{
					System.out.println(person);
				}
			}
			finally
			{
				sqlSession.close();
			}
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
```


```
private static void erstelleDB()
	{
		try
		{
			Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
			Connection connection = DriverManager.getConnection("jdbc:derby:testdb;create=true", "root", "root");

			Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
			statement.execute("CREATE TABLE person (id INT NOT NULL, vorname VARCHAR(200), nachname VARCHAR(200), PRIMARY KEY (id))");
			statement.execute(" INSERT INTO person(id,vorname,nachname) VALUES(1,'Turtle', 'Tau')");
			statement.execute(" INSERT INTO person(id,vorname,nachname) VALUES(2,'Angela', 'Merkel')");
			
			ResultSet resultSet = statement.executeQuery("SELECT * FROM person");
			while (resultSet.next())
			{
				System.out.println(resultSet.getString(1) + "|" + resultSet.getString(2) + "|" + resultSet.getString(3));
			}
			
			statement.close();
			connection.close();
		}
		catch (ClassNotFoundException e)
		{
		}
		catch (SQLException e)
		{
		}
	}
```

*Fehlermeldung*

```
1|Turtle|Tau
2|Angela|Merkel
true
true
true
java.io.IOException: Could not find resource database/SqlMapConfig.xml
	at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:104)
	at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:91)
	at org.apache.ibatis.io.Resources.getResourceAsReader(Resources.java:149)
	at entity.MAIN.main(MAIN.java:32)
```

leider bekomme ich immerzu die oben genannte Fehlermeldung (Unter Ubuntu und Windows 7)!  Ich hoffe jemand kennt den Fehler?

mfg Wepa


----------



## Wepa (21. Mrz 2012)

OK es funktioniert. Es lag an dem Classpath...


----------



## turtle (21. Mrz 2012)

Schön, das es läuft.

Wenn man mehrmals myBATIS genutzt hat, geht die Einrichtung eines Projektes innerhalb von 5 Minuten.

Mir fiel noch auf, dass Du in Deinem Code machst:

```
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
```
Das ist bei den meisten JDBC 4.0 -Treibern nicht mehr notwendig. Diese Treiber registrieren sich automatisch durch die Angabe in META-INF/services/java.sql.Driver. Probier es mal aus und lasse die Class.forName()-Zeile einfach weg.


----------



## Wepa (16. Apr 2012)

Hi,

ich habe noch eine Frage:

MyBatis benutzt eine ObjectFactory um die Objekte zu erstellen, die es braucht.
Wenn man nun factory - Methoden benutzen will, kann man einfach von der *DefaultObjectFactory*
ableiten und diese in der *mybatis-config.xml* myBatis bekannt machen.


```
// ExampleObjectFactory.java

public class ExampleObjectFactory extends DefaultObjectFactory
{
        public Object create(Class type) 
        {
               return super.create(type);
        }

        public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs)
        {
               return super.create(type, constructorArgTypes, constructorArgs);
        }

        public void setProperties(Properties properties)
        {
              super.setProperties(properties);
        }
}
```

[XML]
<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
    <property name="someProperty" value="100"/>
</objectFactory>
[/XML]

Nun nutze ich *myBatis - Spring* und ich möchte AOP benutzen. Wie bekomme ich nun* myBatis - Spring* dazu eine BeanFactory zu benutzen um die Objekte zu erstellen.

mfg Wepa


----------



## turtle (17. Apr 2012)

Dieses kennst Du schon, oder?

Leider nutze ich Spring nicht und kann daher nichts weiter beitragen.


----------

