# Programm baut zu viele MySQL Verbindungen auf



## chris01 (10. Okt 2007)

Hi,

ich verwende den mysql-connector zum Aufbau einer Verbindung zu meinem MySQL server, nun habe ich leider folgendes Problem, während des eintragens baut das Programm sehr viele Verbindungen auf...dadurch ist 1. die performance sehr schlecht und 2. bricht der Server irgendwann ab, nun meine Frage, wie löse ich dieses Problem, das er nur noch eine Verbindung aufbaut und diese dann für die ganze Zeit nutzt?

Hier mal der Code:


```
package de.orangemedia.readclasses;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.commons.codec.digest.DigestUtils;

import de.orangemedia.readclasses.database.*;

public class ImportTagReadIn {

	public static void readTag(String path) throws IOException,
			ClassNotFoundException, SQLException {
		ArrayList<ImportTagGetSet> tags = new ArrayList<ImportTagGetSet>();
		ImportTag database = new ImportTag();
		String str;
		String script = null;
		boolean isScript = false;
		ImportTagGetSet tag = null;
		File dir = new File("<pfad>");
		File[] fileList = dir.listFiles();
		for (File f : fileList) {
			for (String entry : f.list(new TxtFilenameFilter())) {
				BufferedReader in = new BufferedReader(new FileReader(dir + "/"
						+ f.getName() + "/" + entry));
				tags.clear();

				while ((str = in.readLine()) != null) {
					if (str.startsWith("<!--  begin ad tag: ")) {
						tag = new ImportTagGetSet();

						// sitename
						int beginSitename = str.indexOf("P");
						int endSitename = str.indexOf("/");
						String sitename = str.substring(beginSitename,
								endSitename);
						tag.setSitename(sitename);

						// zone
						int endZone = str.indexOf("(");
						String zone = str.substring(endSitename + 1,
								endZone - 2);
						tag.setZone(zone);

						// sizes
						int endSize = str.indexOf(")");
						String size = str.substring(endZone + 1, endSize);
						tag.setSize(size);
					}

					// script und noscript auslesen
					if (str.startsWith("<script")) {
						isScript = true;
						str = str.substring(0, str.length());
						str = str.substring(0, str.length());
						script = new String(str);
					} else if (str.startsWith("<noscript>")) {
						isScript = false;
						tag.setScript(script);
						script = null;
					}

					if (str.startsWith("<noscript>")) {
						isScript = true;
						str = str.substring(0, str.length());
						str = str.substring(0, str.length());
						script = new String(str);
					} else if (str.startsWith("")) {
						isScript = false;
						tag.setNoscript(script);
						tags.add(tag);
						script = null;
					} else {
						if (isScript) {
							script = script + str;
						}
					}
				}
				in.close();

				// Daten in Datenbank speichern

				for (Iterator<ImportTagGetSet> i = tags.iterator(); i.hasNext();) {

					ImportTagGetSet newTag = i.next();
					String script1 = newTag.getScript().substring(53);
					String hash = DigestUtils.md5Hex(script1);

					int exist = database.getHash(hash);
					if (exist == 0) {
						int webSiteId = database
								.webSiteId(newTag.getSitename());
						int TagId = database.insertTag(newTag.getScript(),
								newTag.getNoscript(), newTag.getZone(),
								webSiteId);
						database.parseSize(TagId, newTag.getSize());

					}
				}
				
			}
		}
		database.closeStore();
	}
}
```

ImportTag Klasse


```
package de.util.readclasses.database;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.commons.codec.digest.DigestUtils;

public class ImportTag {
	private static Connection connect;

	public ImportTag() throws ClassNotFoundException, SQLException {
		/** MySQL Datenbanktreiber laden */
		Class.forName("com.mysql.jdbc.Driver");

		/**
		 * Verbindung zur Datenbank aufbauen und Zugangsdaten übergeben
		 * jdbc:mysql://localhost/NamederDatenbank, Benutzername, Passwort
		 */
		ImportTag.connect = DriverManager.getConnection(
				"jdbc:mysql://localhost/test", "user",
				"passwort");
		
	}

	public void closeStore() throws SQLException {
		connect.close();
	}

	/**
	 * 
	 * @param sitename
	 * @return
	 * @throws SQLException
	 */

	public int webSiteId(String sitename) throws SQLException {
		Statement st = connect.createStatement();
		ResultSet rs = st
				.executeQuery("select ID from website where sitename = '"
						+ sitename + "'");
		int webSiteId = 0;
		while (rs.next()) {
			webSiteId = rs.getInt("ID");
		}
		st.close();
		return webSiteId;
	}

	/**
	 * 
	 * @param script
	 * @param noscript
	 * @param zone
	 * @param webSiteId
	 * @return tag_id
	 * @throws SQLException
	 */

	public int insertTag(String script, String noscript, String zone,
			int webSiteId) throws SQLException {

		String script1 = script.substring(53);
		String scriptHash = DigestUtils.md5Hex(script1);

		PreparedStatement stmt = connect
				.prepareStatement(
						"insert into tag(script,noscript,website_id,zone,hashcode) values(?,?,?,?,?)",
						Statement.RETURN_GENERATED_KEYS);
		stmt.setString(1, script);
		stmt.setString(2, noscript);
		stmt.setInt(3, webSiteId);
		stmt.setString(4, zone);
		stmt.setString(5, scriptHash);
		stmt.execute();
		ResultSet rs = stmt.getGeneratedKeys();
		int tag_id = 0;
		if (rs.next())
			tag_id = rs.getInt(1);
		rs.close();
		stmt.close();
		return tag_id;
	}

	/**
	 * 
	 * @param TagId
	 * @param Sizes
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */

	public void parseSize(int TagId, String Sizes)
			throws ClassNotFoundException, SQLException {
		ImportTag data = new ImportTag();
		String sizes = Sizes.replaceAll(" ", "");
		String[] size = sizes.split(",");

		for (int i = 0; i < size.length; i++) {
			Statement st = connect.createStatement();
			ResultSet rs = st
					.executeQuery("select ID from tag_size where size = '"
							+ size[i] + "'");
			int sizeId = 0;
			while (rs.next()) {
				sizeId = rs.getInt("ID");
			}
			data.insertSize(TagId, sizeId);
			st.close();
		}
	}

	/**
	 * 
	 * @param TagId
	 * @param SizeId
	 * @throws SQLException
	 */

	public void insertSize(int TagId, int SizeId) throws SQLException {
		Statement st = connect.createStatement();
		st.execute("insert into size_id(tag_id,size_id) VALUES('" + TagId
				+ "','" + SizeId + "')");
		st.close();
	}

	/**
	 * 
	 * @param size
	 * @throws SQLException
	 */

	public void insertSize(String size) throws SQLException {
		Statement st = connect.createStatement();
		st.execute("INSERT into tag_size(size) VALUES('" + size + "')");
		st.close();
	}

	/**
	 * 
	 * @param hash
	 * @return
	 * @throws SQLException
	 */

	public int getHash(String hash) throws SQLException {
		Statement st = connect.createStatement();
		ResultSet rs = st.executeQuery("select ID from tag where hashcode = '"
				+ hash + "'");
		rs.last();
		int result = rs.getRow();
		st.close();
		return result;
	}

	/**
	 * 
	 * @param size
	 * @return
	 * @throws SQLException
	 */

	public int getDuplicateSize(String size) throws SQLException {
		Statement st = connect.createStatement();
		ResultSet rs = st.executeQuery("select ID from tag_size where size = '"
				+ size + "'");
		rs.last();
		int result = rs.getRow();
		st.close();
		return result;

	}
	
}
```

Danke und Gruß

Chris


----------



## Guest (10. Okt 2007)

Es sollte reichen, wenn du im aktuellen Code die Verbindung wieder schliessen würdest.
Siehe z.B. parseSize(...)
Du erstellst dort immer wieder ImportTag Instanzen, schliesst die Verbindung aber nicht.
Dann innerhalb der Schleife u.U. viele Statements, wo ein PreparedStatement (ausserhalb 
der Schleife) die bessere Wahlt wäre. Du Schliesst auch nicht immer die ResultSets, was
dazu führt, dass sie erst mit dem Schliessen des Statements freigegeben werden.
Das alles kostet Zeit und Ressourcen. Sollten an irgendeiner Stelle SQLException kommen,
werden weder die Statements, noch die ResultSets freigegeben. Sehr unsicher das ganze.
Das mit dem Class.forName("com.mysql.jdbc.Driver"); brauchst du auch nur einmalig, nicht 
jedes mal, wenn eine ImportTag Instanz erstellt wird.

Um auf deine eigentliche Frage zu kommen. Du könntest eine Singleton-Klasse schreiben, 
nennen wir sie mal ServiceLocator, die dir die Connection erstellt. Freigeben/Schliessen musst 
du sie aber da, wo sie nicht mehr benötigt werden.


----------



## Guest (10. Okt 2007)

Hi,

erstmal vielen Dank für deine Antwort!...
Leider ist mir noch etwas schleierhaft, wo genau ich das ganze jetzt wieder schließen/freigeben muss...könntest du mir evtl. ein kleines Beispiel machen?

Gruß

Chris


----------



## Guest (10. Okt 2007)

So ungefähr
	
	
	
	





```
Connection connection = null;
PreparedStatement statement = null;
try
{
   connection = DBUtil.getConnection(); // neue Connection erstellen oder immmer wieder die gleiche zurückgeben
   statement = connection.prepareStatement(...)
   ...
}
catch(SQLException e)
{
   // Fehlerbehandlung, Logger
}
finally
{
   // Statement schliessen, wenn nicht null.
   DBUtil.safeClose(statement);
   // Connection schliessen oder nix tun, falls nur eine verwendet wird
   DBUtil.safeClose(connection);
}
```


----------



## L-ectron-X (10. Okt 2007)

Die Connection sollte unbedingt static sein. Achte darauf, dass dann auch nur noch diese Connection zurückgegeben wird.


----------

