<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Information Centre &#187; DB</title>
	<atom:link href="http://my.center-of.info/category/db/feed/" rel="self" type="application/rss+xml" />
	<link>http://my.center-of.info</link>
	<description>“Wenn etwas schon da war, wie kann man es dann patentieren?” D.E.Knuth, 2002</description>
	<lastBuildDate>Sat, 22 Oct 2011 11:09:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Derby Export</title>
		<link>http://my.center-of.info/2011/04/22/derby-export/</link>
		<comments>http://my.center-of.info/2011/04/22/derby-export/#comments</comments>
		<pubDate>Fri, 22 Apr 2011 09:39:59 +0000</pubDate>
		<dc:creator>Haf</dc:creator>
				<category><![CDATA[DB]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://my.center-of.info/?p=179</guid>
		<description><![CDATA[Beim Einsatz der Java Derby Datenbank kommt irgendwann der Wunsch einzelne Daten oder eine komplette Tabelle zu exportieren. Hierfür bietet Derby verschiedene Procedures an: SYSCS_UTIL.SYSCS_EXPORT_TABLE: Zum exportieren einer kompletten Tabelle SYSCS_UTIL.SYSCS_EXPORT_QUERY: Exportiert die Daten, die dem mitgegebenen SELECT entsprechen SYSCS_UTIL.SYSCS_BACKUP_DATABASE: Kompletter Backup der DB. Die Export-Procedures liefern eine CSV-Datei, wobei man die Trennzeichen definieren kann. [...]]]></description>
			<content:encoded><![CDATA[<p>Beim Einsatz der Java Derby Datenbank kommt irgendwann der Wunsch einzelne Daten oder eine komplette Tabelle zu exportieren. Hierfür bietet Derby verschiedene Procedures an:</p>
<ul>
<li>SYSCS_UTIL.SYSCS_EXPORT_TABLE: Zum exportieren einer kompletten Tabelle</li>
<li>SYSCS_UTIL.SYSCS_EXPORT_QUERY: Exportiert die Daten, die dem mitgegebenen SELECT entsprechen</li>
<li>SYSCS_UTIL.SYSCS_BACKUP_DATABASE: Kompletter Backup der DB.</li>
</ul>
<p><span id="more-179"></span></p>
<p>Die Export-Procedures liefern eine CSV-Datei, wobei man die Trennzeichen definieren kann.<br />
Beim Backup-Procedure wird die ganze Ordnerstruktur in einen gewünschten Ordner kopiert.</p>
<p>Zum Exportieren einer ganzen Tabelle sieht die Signatur der Procedure wie folgt aus:</p>
<pre class="brush: sql">
SYSCS_UTIL.SYSCS_EXPORT_TABLE (
	IN SCHEMANAME  VARCHAR(128),
	IN TABLENAME VARCHAR(128),
	IN FILENAME VARCHAR(32672),
	IN COLUMNDELIMITER CHAR(1),
	IN CHARACTERDELIMITER CHAR(1),
	IN CODESET VARCHAR(128)
)
</pre>
<p>&#8230;für eine definierte Datenmenge</p>
<pre class="brush: sql">
SYSCS_UTIL.SYSCS_EXPORT_QUERY(
	IN SELECTSTATEMENT VARCHAR(32672),
	IN FILENAME VARCHAR(32672),
	IN COLUMNDELIMITER CHAR(1),
	IN CHARACTERDELIMITER CHAR(1),
	IN CODESET VARCHAR(128)
)
</pre>
<p>Beispielhaft (mit JPA)</p>
<pre class="brush: java">
public void exportTable()
{
	final Object[] paras = new Object[6];
	paras[0] = „DB-SCHEMA“;
	paras[1] = „TABLE-NAME“;
	paras[2] = „EXPORT-FILE-PATH.csv“;
	// Column delimiter
	paras[3] = &#039;;&#039;;
	// character delimiter
	paras[4] = &#039;|&#039;;
	// Codeset
	paras[5] = „UTF-8“;

	callProcedure(„{call SYSCS_UTIL.SYSCS_EXPORT_TABLE (?,?,?,?,?,?)}“, paras);
}

public void exportData()
{
	final Object[] paras = new Object[5];
	paras[0] = „SELECT * FROM TABLE-NAME WHERE id IN (1, 2, 99) AND ...“;
	paras[1] = „EXPORT-FILE-PATH.csv“;
	// Column delimiter
	paras[2] = &#039;;&#039;;
	// character delimiter
	paras[3] = &#039;|&#039;;
	// Codeset
	paras[4] = „UTF-8“;

	callProcedure(„{call SYSCS_UTIL.SYSCS_EXPORT_TABLE (?,?,?,?,?,?)}“, paras);
}

public void callProcedure(final String sql, final Object... parameters)
{
	final Query query = entityManager.createNativeQuery(sql);
	int counter = 1;
	for(Object o: parameters)
	{
		query.setParameter(i++, o);
	}

}
</pre>
<p>Links:</p>
<ul>
<li>Derby DB: <a href="http://db.apache.org/derby/">http://db.apache.org/derby/</a></li>
<li>Derby Referenz Guide &#8211; Export Data: <a href="http://db.apache.org/derby/docs/10.7/ref/ref-single.html#rrefexportselectionproc">http://db.apache.org/derby/docs/10.7/ref/ref-single.html#rrefexportselectionproc</a>
</li>
<li>Derby Referenz Guide – Export Table: <a href="http://db.apache.org/derby/docs/10.7/ref/ref-single.html#rrefexportproc">http://db.apache.org/derby/docs/10.7/ref/ref-single.html#rrefexportproc</a></li>
<li>Derby Referenz Guide – Backup: <a href="http://db.apache.org/derby/docs/10.7/ref/ref-single.html#rrefbackupdbproc">http://db.apache.org/derby/docs/10.7/ref/ref-single.html#rrefbackupdbproc</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://my.center-of.info/2011/04/22/derby-export/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JPA: Dynamic Datasource Routing</title>
		<link>http://my.center-of.info/2011/03/04/jpa-dynamic-datasource-routing/</link>
		<comments>http://my.center-of.info/2011/03/04/jpa-dynamic-datasource-routing/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 20:15:54 +0000</pubDate>
		<dc:creator>Haf</dc:creator>
				<category><![CDATA[DB]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://my.center-of.info/?p=158</guid>
		<description><![CDATA[Man stelle sich vor, in einer (Web-)Anwendung müssen verschiedene Datasources verwendet werden. Ob bei den unterschiedlichen Datasourcen es sich immer um die andere/gleiche Datenbank handelt, sei mal dahingestellt. Die Datasourcen unterscheiden sich mind. in einer Eigenschaft, z.B. User. Im Spring-Kontext gilt folgendes: In JPA braucht man pro EntityManagerFactory eine Datasource. Der EMF ist einen TransactionManager [...]]]></description>
			<content:encoded><![CDATA[<p>Man stelle sich vor, in einer (Web-)Anwendung müssen verschiedene Datasources verwendet werden. Ob bei den unterschiedlichen Datasourcen es sich immer um die andere/gleiche Datenbank handelt, sei mal dahingestellt. Die Datasourcen unterscheiden sich mind. in einer Eigenschaft, z.B. User.</p>
<p><span id="more-158"></span></p>
<p>Im Spring-Kontext gilt folgendes: In JPA braucht man pro EntityManagerFactory eine Datasource. Der EMF ist einen TransactionManager zugeordnet.</p>
<p>Man könnte alle Datasource, EMF, TX-Manager und PUs in Spring konfigurieren. Man hat jedoch ein Problem, wenn man n verschiedene Datasourcen hat, die zur Laufzeit ausgewählt werden müssen.</p>
<ul>
<li>Die Konfiguration ist umfangreich und unübersichtlich
<ul>
<li>Pro Datasource ist ein Persistence-Unit notwendig, denn für die Ermittlung des richtigen EntityManager kann @<a title="JEE 5 API: PersistenceContext" href="http://download.oracle.com/javaee/5/api/javax/persistence/PersistenceContext.html" target="_blank">PersistenceContext</a>(unitName = &#8220;PU_NAME&#8221;) verwendet werden</li>
<li>Pro Datasource einen EntityManagerFactory mit der Verknüpfung zur PersistenceUnit</li>
<li>Pro EntityManagerFactory einen TransactionManager, ggf. mit <a title="Spring 3 Reference Doc: Qualifier" href="http://static.springsource.org/spring/docs/3.0.x/reference/beans.html#beans-autowired-annotation-qualifiers" target="_blank">Qualifier</a>.</li>
</ul>
</li>
<li>Die Wartung ist entsprechend nicht optimal. Pro neue Datasource müssen 3 Stellen angepasst werden</li>
<li>Das Transaction-Handling wird kompliziert. @<a title="Spring 3 API: Transactional" href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/transaction/annotation/Transactional.html" target="_blank">Transactional</a> muss nun immer den richtigen TransactionManager nutzen. Die Entscheidung soll natürlich zur Laufzeit passieren. @Transactional(&#8220;TX_MANAGER_NAME&#8221;) reicht nicht aus, da es eine statische Kopplung verursacht.</li>
</ul>
<p>Eine andere Lösungsvariante wäre, statt einen <a title="JEE 5 API: EntityManager" href="http://download.oracle.com/javaee/5/api/javax/persistence/EntityManager.html">EntityManager</a> durch @PersitenceContext eher direkt den <a title="JEE 5 API: EntityManagerFactory" href="http://download.oracle.com/javaee/5/api/javax/persistence/EntityManagerFactory.html">EntityManagerFactory</a> durch @<a title="JEE 5 API: PersistenceUnit" href="http://download.oracle.com/javaee/5/api/javax/persistence/PersistenceUnit.html">PersistenceUnit</a> zu bekommen. Hier modifiziert man die EntityManager-Erstellung soweit, dass man den EntityManager mit der gewünschten Datasource bekommt. Falls sich bei den Datasourcen nur die User unterscheiden und <a title="Eclipselink JPA" href="http://www.eclipse.org/eclipselink/jpa.php" target="_blank">Eclipselink</a> verwendet wird, siehe u.a. [1].</p>
<p>Perfekt wäre jedoch eine Lösung, in der nur EntityManagerFactory, ein TransactionManager und ein PersistenceUnit verwendet wird. Zur Laufzeit soll dann der vorhandene EntityManagerFactory für die gewünschte Datasource einen EntityManager erstellen.</p>
<p>Das funktioniert. Der EntityManagerFactory erwartet eine Referenz auf die <a title="Java 5 API: DataSource" href="http://download.oracle.com/javase/1.5.0/docs/api/javax/sql/DataSource.html" target="_blank">DataSource</a>. Hier könnte man eine eigene Implementierung dieses Interface anbieten, welches die Unterscheidung bzgl. der verschiedenen Datasourcen durchführt. DataSource.getConnection() muss dann abhängig von fest definierten Eigenschaften die Connection von der richtigen Datasource zurückgeben. Um die Eigenschaften in der eigenen DataSource-Implementierung abzufragen, ist die Nutzung von <a title="Java 5 API: ThreadLocal" href="http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ThreadLocal.html" target="_blank">ThreadLocal</a> bzw. <a title="Java 5 API: InheritableThreadLocal" href="http://download.oracle.com/javase/1.5.0/docs/api/java/lang/InheritableThreadLocal.html" target="_blank">InheritableThreadLocal</a> möglich.</p>
<p>Eine Spring-spezifische Lösung die in diese Richtung geht, ist mittels <a title="Spring 3 API: AbstractRoutingDataSource" href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.html" target="_blank">AbstractRoutingDatasource</a> möglich [2]. Hier muss die abstrakte Methode determineCurrentLookupKey() implementiert werden. In dieser Methode muss die Logik verpackt werden, damit anhand des resultierenden Keys die richtige Datasource verwendet werden kann. Das Mapping zwischen Key und Datasource wird in AbstractRoutingDatasources#<a title="Spring 3 API: AbstractRoutingDataSource.setTargetDataSources()" href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.html#setTargetDataSources(java.util.Map)" target="_blank">targetDataSources</a> gehalten. Wird kein Key zurückgeliefert, wird die vorher definierte Standard-Datasource verwendet.</p>
<p>Eine Beispiel-Implementierung, welches mit Spring 3.x und jeweils mit Eclipselink und Hibernate funktioniert, sieht wie folgt aus:</p>
<p>Die relevante Spring-Konfiguration:</p>
<pre class="brush: xml">
&lt;bean id=&quot;baseDataSource&quot; abstract=&quot;true&quot;&gt;
&lt;property name=&quot;driverClassName&quot; value=&quot;${db.driverClassName}&quot;/&gt;
&lt;property name=&quot;url&quot; value=&quot;${db.url}&quot;/&gt;
&lt;/bean&gt;

&lt;bean id=&quot;dataSource1&quot; parent=&quot;baseDataSource&quot;&gt;
&lt;property name=&quot;user&quot; value=&quot;${db.1.user}&quot;/&gt;
&lt;property name=&quot;password&quot; value=&quot;${db.1.pw}&quot;/&gt;
&lt;/bean&gt;
&lt;bean id=&quot;dataSource2&quot; parent=&quot;baseDataSource&quot;&gt;
&lt;property name=&quot;user&quot; value=&quot;${db.2.user}&quot;/&gt;
&lt;property name=&quot;password&quot; value=&quot;${db.2.pw}&quot;/&gt;
&lt;/bean&gt;
&lt;bean id=&quot;dataSource3&quot; parent=&quot;baseDataSource&quot;&gt;
&lt;property name=&quot;user&quot; value=&quot;${db.3.user}&quot;/&gt;
&lt;property name=&quot;password&quot; value=&quot;${db.3.pw}&quot;/&gt;
&lt;/bean&gt;

&lt;bean id=&quot;dynamicDatasource&quot; class=&quot;info.center-of.spring.jpa.DynamicDataSourceRouting&quot;&gt;
&lt;property name=&quot;targetDataSources&quot;&gt;
&lt;entry key=&quot;${db.1.user}&quot; value-ref=&quot;dataSource1&quot;/&gt;
&lt;entry key=&quot;${db.2.user}&quot; value-ref=&quot;dataSource2&quot;/&gt;
&lt;entry key=&quot;${db.3.user}&quot; value-ref=&quot;dataSource3&quot;/&gt;
&lt;/property&gt;
&lt;property name=&quot;defaultTargetDataSource&quot; ref=&quot;dataSource1&quot;/&gt;
&lt;/bean&gt;

&lt;bean id=&quot;entityManagerFactory&quot; class=&quot;org.springframework.orm.jpa.LocalEntityManagerFactoryBean&quot;&gt;
&lt;property name=&quot;datasource&quot; ref=&quot;dynamicDatasource&quot; /&gt;
&lt;property name=&quot;jpaVendorAdapter&quot;&gt;
&lt;!-- Fuer Hibernate --&gt;
&lt;bean class=&quot;org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter&quot; p:showSql=&quot;true&quot; generateDdl=&quot;true&quot; /&gt;
&lt;!-- Fuer Eclipselink
&lt;bean class=&quot;org.springframework.orm.jpa.vendor.EclipselinkJpaVendorAdapter&quot; p:showSql=&quot;true&quot; generateDdl=&quot;true&quot; /&gt;
--&gt;
&lt;/property&gt;
&lt;/bean&gt;

&lt;bean class=&quot;org.springframework.orm.jpa.JpaTransactionManager&quot;&gt;
&lt;property name=&quot;entityManagerFactory&quot; ref=&quot;entityManagerFactory&quot; /&gt;
&lt;/bean&gt;

&lt;tx:annotation-driven /&gt;
</pre>
<p>Die Klasse <em>DynamicDataSourceRouting</em> überschreibt die Methode zur Ermittlung des Keys. In unserem Fall ist dies immer der aktuelle/gewünschte DB-User:</p>
<pre class="brush: java">
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class CustomerRoutingDataSource extends AbstractRoutingDataSource {

@Override
protected Object determineCurrentLookupKey() {
return DBUserContextHolder.getDBUser();
}
}
</pre>
<p><em>DBUserContextHolder</em> ist eine Klasse mit einer ThreadLocal-Variable, die in dem aktuellen Thread den DB-User hält</p>
<pre class="brush: java">
public class DBUserContextHolder {

private static final InheritableThreadLocal&lt;String&gt; contextHolder = new InheritableThreadLocal&lt;String&gt;();

public static void setDBUser(final String dbUser) {
contextHolder.set(dbUser);
}

public static String getDBUser() {
return (String) contextHolder.get();
}

public static void clear() {
contextHolder.remove();
}
}
</pre>
<p>Bevor der EntityManager nun erstellt wird, muss</p>
<pre class="brush: java">
DBUserContextHolder.setDBUser(&amp;quot;dbUser1&amp;quot;);
</pre>
<p>aufgerufen werden.</p>
<p>Mit dieser Lösung hat man &#8220;nur&#8221; eine enge Kopplung mit Spring. Die Lösung funktioniert mit verschiedenen ORMs.</p>
<p>&nbsp;</p>
<p>[1]: <a title="Wikibook JPA: Java Persistence/Auditing and Security - Provide each application user with a database user id" href="http://en.wikibooks.org/wiki/Java_Persistence/Auditing_and_Security" target="_blank">Wikibook JPA: Provide each application user with a database user id</a></p>
<p>[2]: <a title="Spring Blog: Dynamic DataSource Routing" href="http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/" target="_blank">Spring Blog: Dynamic DataSource Routing</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://my.center-of.info/2011/03/04/jpa-dynamic-datasource-routing/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SQL: Constraints hinzufügen</title>
		<link>http://my.center-of.info/2009/05/18/sql-constraints-hinzufuegen/</link>
		<comments>http://my.center-of.info/2009/05/18/sql-constraints-hinzufuegen/#comments</comments>
		<pubDate>Mon, 18 May 2009 08:38:18 +0000</pubDate>
		<dc:creator>Haf</dc:creator>
				<category><![CDATA[DB]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://my.center-of.info/?p=124</guid>
		<description><![CDATA[Beim Leeren von Datenbank-Tabellen müssen immer die vorhandenen Constraints beachtet werden. Das Löschen von Tabellen-Zeilen, obwohl andere darauf verweisen, ist nicht erlaubt (referenzielle Integrität). Versucht man es doch (mittels TRUNCATE [1]) kriegt man eine Fehlermeldung. Hier kann man nun entweder DELETE Statements [2] nutzen, was länger dauern kann, oder man verwendet doch TRUNCATE und muss [...]]]></description>
			<content:encoded><![CDATA[<p>Beim Leeren von Datenbank-Tabellen müssen immer die vorhandenen Constraints beachtet werden. Das Löschen von Tabellen-Zeilen, obwohl andere darauf verweisen, ist nicht erlaubt (referenzielle Integrität).<br />
Versucht man es doch (mittels TRUNCATE [1]) kriegt man eine Fehlermeldung.<br />
Hier kann man nun entweder DELETE Statements [2] nutzen, was länger dauern kann, oder man verwendet doch TRUNCATE und muss die vorhandenen Constraints löschen.</p>
<pre class="brush: sql">
ALTER TABLE TableName DROP CONSTRAINT FK_ConstraintName
</pre>
<p>Durch das Löschen aller Constraints der betroffenen Tabelle kann diese dann mit TRUNCATE geleert werden.<br />
Zum Hinzufügen der Constraints:</p>
<pre class="brush: sql">
ALTER TABLE TableName WITH CHECK ADD CONSTRAINT FK_ConstraintsName
	FOREIGN KEY (columnName) REFERENCES TableNameReference (id)
</pre>
<p>Constraints können nur dann hinzugefügt werden, wenn sie nicht vorhanden sind. Mit einer Prüfung sieht das dann so aus:</p>
<pre class="brush: sql">
IF NOT EXISTS (SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
                         WHERE TABLE_NAME=&#039;TableName&#039;
			     AND CONSTRAINT_NAME=&#039;FK_ConstraintName&#039;
			     AND CONSTRAINT_TYPE=&#039;FOREIGN KEY&#039;)
   /* SQL Statement to add constraint, see above listing */
</pre>
<p>Links:<br />
[1] SQL Drop (<a href="http://www.w3schools.com/SQL/sql_drop.asp" target="_blank">TRUNCATE</a>)<br />
[2] SQL <a href="http://www.w3schools.com/Sql/sql_delete.asp" target="_blank">DELETE</a><br />
[3] SQL <a href="http://www.w3schools.com/SQL/sql_foreignkey.asp" target="_blank">FK Constraints</a></p>
]]></content:encoded>
			<wfw:commentRss>http://my.center-of.info/2009/05/18/sql-constraints-hinzufuegen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

