Problema com PreparedStatement no HSQLDB

6 respostas
rafaelveggi

Boa noite a todos
Estou com um problema um pouco bizarro :shock:
Estou usando preparedStatement para criar meu banco de dados a partir de um diretório do sistema de arquivos.
Crio as tabelas perfeitamente, mas na hora de realizar os INSERTS, o preparedStatement parece esquecer de algumas linhas…
Procurando pelo erro, utilizei 2 JOptionPanes para me apontarem o “percurso” dos dados enquanto estavam sendo inseridos (os dois estão comentados no código abaixo). Quando uso os JOptionPanes, os inserts funcionam e o banco de dados é preenchido corretamente.
Alguém já passou por isso?
Eu estou me esquecendo de alguma coisa?

import java.io.*;
import java.sql.*; 
import java.util.Properties;

import javax.swing.*;

public class DBGenerator {
	private Connection con;
	private Statement stm;
	private PreparedStatement pstm;
	private MyProperties properties = MyProperties.getInstance();
	private String
		driver = properties.getProperty("DB_DRIVER"),
		url = properties.getProperty("DB_URL"),
		user = properties.getProperty("DB_USER"),
		password = properties.getProperty("DB_PASSWORD"),
		path = properties.getProperty("MUSIC_DIRECTORY"),
		dbHome = properties.getProperty("DB_HOME");

	public DBGenerator() {
		deleteDBFiles();
		createDB();
		insertDB();
	}
	
	public void insertDB() {
		
		String insertStyle = properties.getProperty("INSERT_STYLE");
		String insertArtist = properties.getProperty("INSERT_ARTIST");
		String insertAlbum = properties.getProperty("INSERT_ALBUM");
		String insertSong = properties.getProperty("INSERT_SONG");
		String updateStyle = properties.getProperty("UPDATE_STYLE");
		String updateArtist = properties.getProperty("UPDATE_ARTIST");
		String updateAlbum = properties.getProperty("UPDATE_ALBUM");
		
		int iArtist = -1;
		int iAlbum = -1;
		int iSong = -1;
		try {
			con = DriverManager.getConnection(url, user, password);

			File musicDir = new File(path);
			String[] styles = musicDir.list();
			
			for(int i = 0; i < styles.length; i++) {
				File f1 = new File(musicDir + File.separator + styles[i]);

				if(f1.isDirectory()) {
					pstm = con.prepareStatement(insertStyle);
					pstm.setInt(1, i);
					pstm.setString(2, styles[i]);
					pstm.executeUpdate();					
//					JOptionPane.showMessageDialog(null, f1.getAbsoluteFile() + " " + i
//							+ "\n" + insertStyle + " " + i + " " + styles[i]);
					String[] artists = f1.list();
					for(int j = 0; j < artists.length; j++) {						
						File f2 = new File(f1 + File.separator + artists[j]);
						if(f2.isDirectory()) {							
							pstm = con.prepareStatement(insertArtist);
							pstm.setInt(1, ++iArtist);
							pstm.setString(2, artists[j]);
							pstm.setInt(3, i);
							pstm.executeUpdate();
							String[] albums = f2.list();
							for(int k = 0; k < albums.length; k++) {
								File f3 = new File(f2 + File.separator + albums[k]);
								if(f3.isDirectory()) {
									String[] songs = f3.list();
									pstm = con.prepareStatement(insertAlbum);
									pstm.setInt(1, ++iAlbum);
									pstm.setString(2, albums[k]);
									pstm.setInt(3, iArtist);
									pstm.executeUpdate();
									for(int l = 0; l < songs.length; l++) {
										if((songs[l].contains(".jpg")) || (songs[l].contains(".jpeg")) || (songs[l].contains(".png"))) {
											String s = f3 + File.separator + songs[l];
											pstm = con.prepareStatement(updateAlbum);
											pstm.setString(1, s);
											pstm.setInt(1, iAlbum);
											pstm.executeUpdate();
										} else {
											int format = 0;
											if(songs[l].contains(Constants.AUDIO_FORMAT)) {
												format = 1;
											} else if(songs[l].contains(Constants.VIDEO_FORMAT)) {
												format = 2;
											}
											pstm = con.prepareStatement(insertSong);//FIXME execution e length no random
											pstm.setInt(1, ++iSong);
											pstm.setString(2, songs[l]);
											pstm.setInt(3, format);
											pstm.setInt(4, (int)(1000 * Math.random()));
											pstm.setInt(5, iAlbum);
											pstm.setInt(6, (int)(1000 * Math.random()));
											pstm.executeUpdate();
										}
									}
								} else if((f3.toString().contains(".jpg")) || 
										(f3.toString().contains(".jpeg")) || 
										(f3.toString().contains(".png"))){
									pstm = con.prepareStatement(updateArtist);
									pstm.setString(1, f3.getAbsolutePath());
									pstm.setInt(2, iArtist);
									pstm.executeUpdate();
								}
							}
						} else if((f2.toString().contains(".jpg")) || 
								(f2.toString().contains(".jpeg")) || 
								(f2.toString().contains(".png"))){
							pstm = con.prepareStatement(updateStyle);
							pstm.setString(1, f2.getAbsolutePath());
							pstm.setInt(2, i);
							pstm.executeUpdate();
						}
					}
				} else {
//					JOptionPane.showMessageDialog(null, f1.getAbsoluteFile() + "\nEstá no diretório errado...");
				}
			}
		} catch(SQLException e) { 
			JOptionPane.showMessageDialog(null, "sql exception");
			e.printStackTrace();
		} finally {
			try {
				con.close();
			} catch(SQLException onConClose) {
				JOptionPane.showMessageDialog(null, "Houve erro no fechamento da conexão");
				onConClose.printStackTrace();
			}
		}
	}

	public void createDB() {
		String createStyle = properties.getProperty("CREATE_STYLE");
		String createArtist = properties.getProperty("CREATE_ARTIST");
		String createAlbum = properties.getProperty("CREATE_ALBUM");
		String createSong = properties.getProperty("CREATE_SONG");
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, user, password);
			stm = con.createStatement();
			stm.executeQuery(createStyle + createArtist + createAlbum + createSong);
			
		} catch(ClassNotFoundException e){
			JOptionPane.showMessageDialog(null, "Classe nao encontrada");
			e.printStackTrace();
		} catch(SQLException e) { 
			JOptionPane.showMessageDialog(null, "Excessão SQL");
			e.printStackTrace();
		} finally {
			try {
				stm.execute("SHUTDOWN");
				con.close();
			} catch(SQLException onConClose) {
				JOptionPane.showMessageDialog(null, "Houve erro no fechamento da conexão");
				onConClose.printStackTrace();
			}
		}
	}
	
	public void deleteDBFiles() {
		try {
			File[] dbFiles = new File(dbHome).listFiles();
			for(int i = 0; i < dbFiles.length; i++) {
				dbFiles[i].delete();
			}
		} catch(SecurityException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		new DBGenerator();
	}
}

Obrigado a todos

6 Respostas

_fs

Não reutilize o mesmo objeto PreparedStatement para queries diferentes. Provavelmente resolverá seu problema.

rafaelveggi

Obrigado, LIPE!
Segui sua dica e declaro cada PreparedStatement, mas continuo com o mesmo problema…
Também adicionei um close() a cada preparedStatement e nada…
Por exemplo, minha tabela de artistas deve conter oito entradas.
. Quando os dois JOptionPanes estão comentados, só são inseridas 3 linhas
. Quando apenas o segundo está comentado, são inseridas 6 linhas
. Quando os dois estão rodando, são inseridas 8 linhas

Além do pstm.executeUpdate() eu teria que utilizar algum outro método?
Dá pra entender isso? :shock:

Obrigado a todos

Código modificado

import java.io.*;
import java.sql.*; 
import java.util.ArrayList;

import javax.swing.*;

public class DBLayer {
	private static DBLayer instance;
	private Connection con;
	private Statement stm;
//	private PreparedStatement pstm;
	private MyProperties properties = MyProperties.getInstance();
	private String
		driver = properties.getProperty("DB_DRIVER"),
		url = properties.getProperty("DB_URL"),
		user = properties.getProperty("DB_USER"),
		password = properties.getProperty("DB_PASSWORD"),
		path = properties.getProperty("MUSIC_DIRECTORY"),
		dbHome = properties.getProperty("DB_HOME");
	
	private DBLayer() {}
	
	public static DBLayer getInstance() {
		if (instance == null) {
			instance = new DBLayer();
		}
		return instance;
	}
	
	public ArrayList<Object[]> getTableData(String sql) {
		ArrayList<Object[]> array = new ArrayList<Object[]>();
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, user, password);
			stm = con.createStatement();
			ResultSet rs = stm.executeQuery(sql);
			ResultSetMetaData rsmd = rs.getMetaData();
			while(rs.next()) {
				Object[] o = new Object[rsmd.getColumnCount()];
				for(int i = 0; i < o.length; i++) {
					o[i] = rs.getObject(i + 1).toString();
				}
				array.add(o);
			}
		} catch (SQLException e) {
			JOptionPane.showMessageDialog(null, "Excessão SQL em getStyleData");
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			JOptionPane.showMessageDialog(null, "ClassNotFoundException em getStyleData");
			e.printStackTrace();
		}
		return array;
	}
	
	public void insertDB() {
		
		String insertStyle = properties.getProperty("INSERT_STYLE");
		String insertArtist = properties.getProperty("INSERT_ARTIST");
		String insertAlbum = properties.getProperty("INSERT_ALBUM");
		String insertTitle = properties.getProperty("INSERT_TITLE");
		String updateStyle = properties.getProperty("UPDATE_STYLE");
		String updateArtist = properties.getProperty("UPDATE_ARTIST");
		String updateAlbum = properties.getProperty("UPDATE_ALBUM");
		
		int iArtist = -1;
		int iAlbum = -1;
		int iTitle = -1;
		try {
			con = DriverManager.getConnection(url, user, password);

			File musicDir = new File(path);
			String[] styles = musicDir.list();
			
			for(int i = 0; i < styles.length; i++) {
				File stylesDir = new File(musicDir + File.separator + styles[i]);

				if(stylesDir.isDirectory()) {
					PreparedStatement pstm0 = con.prepareStatement(insertStyle);
					pstm0.setInt(1, i);
					pstm0.setString(2, styles[i]);
					pstm0.executeUpdate();
					pstm0.close();
					//primeiro JOptionPane
					JOptionPane.showMessageDialog(null, stylesDir.getAbsoluteFile() + " " + i
							+ "\n" + insertStyle + " " + i + " " + styles[i]);
					String[] artists = stylesDir.list();
					for(int j = 0; j < artists.length; j++) {						
						File artistsFile = new File(stylesDir + File.separator + artists[j]);
						if(artistsFile.isDirectory()) {							
							PreparedStatement pstm1 = con.prepareStatement(insertArtist);
							pstm1.setInt(1, ++iArtist);
							pstm1.setString(2, artists[j]);
							pstm1.setInt(3, i);
							pstm1.executeUpdate();
							pstm1.close();
							String[] albums = artistsFile.list();
							for(int k = 0; k < albums.length; k++) {
								File albumsFile = new File(artistsFile + File.separator + albums[k]);
								if(albumsFile.isDirectory()) {
									String[] songs = albumsFile.list();
									PreparedStatement pstm2 = con.prepareStatement(insertAlbum);
									pstm2.setInt(1, ++iAlbum);
									pstm2.setString(2, albums[k]);
									pstm2.setInt(3, iArtist);
									pstm2.executeUpdate();
									pstm2.close();
									for(int l = 0; l < songs.length; l++) {
										if((songs[l].contains(".jpg")) || 
												(songs[l].contains(".jpeg")) || 
												(songs[l].contains(".png"))) 
										{
											String s = albumsFile + File.separator + songs[l];
											PreparedStatement pstm3 = con.prepareStatement(updateAlbum);
											pstm3.setString(1, s);
											pstm3.setInt(1, iAlbum);
											pstm3.executeUpdate();
											pstm3.close();
										} else {
											int format = 0;
											if(songs[l].contains(Constants.AUDIO_FORMAT)) {
												format = 1;
											} else if(songs[l].contains(Constants.VIDEO_FORMAT)) {
												format = 2;
											}
											PreparedStatement pstm3 = con.prepareStatement(insertTitle);//FIXME execution e length no random
											pstm3.setInt(1, ++iTitle);
											pstm3.setString(2, songs[l]);
											pstm3.setInt(3, format);
											pstm3.setInt(4, (int)(1000 * Math.random()));
											pstm3.setInt(5, iAlbum);
											pstm3.setInt(6, (int)(1000 * Math.random()));
											pstm3.executeUpdate();
											pstm3.close();
										}
									}
								} else if((albumsFile.toString().contains(".jpg")) || 
										(albumsFile.toString().contains(".jpeg")) || 
										(albumsFile.toString().contains(".png")))
								{
									PreparedStatement pstm2 = con.prepareStatement(updateArtist);
									pstm2.setString(1, albumsFile.getAbsolutePath());
									pstm2.setInt(2, iArtist);
									pstm2.executeUpdate();
									pstm2.close();
								}
							}
						} else if((artistsFile.toString().contains(".jpg")) || 
								(artistsFile.toString().contains(".jpeg")) || 
								(artistsFile.toString().contains(".png")))
						{
							PreparedStatement pstm1 = con.prepareStatement(updateStyle);
							pstm1.setString(1, artistsFile.getAbsolutePath());
							pstm1.setInt(2, i);
							pstm1.executeUpdate();
							pstm1.close();
						}
					}
				} else {
					//segundo JOptionPane
					JOptionPane.showMessageDialog(null, stylesDir.getAbsoluteFile() + "\nEstá no diretório errado...");
				}
			}
		} catch(SQLException e) { 
			JOptionPane.showMessageDialog(null, "sql exception");
			e.printStackTrace();
		} finally {
			try {
				con.close();
			} catch(SQLException onConClose) {
				JOptionPane.showMessageDialog(null, "Houve erro no fechamento da conexão");
				onConClose.printStackTrace();
			}
		}
	}

	public void createDB() {
		deleteDBFiles();

		String createStyle = properties.getProperty("CREATE_STYLE");
		String createArtist = properties.getProperty("CREATE_ARTIST");
		String createAlbum = properties.getProperty("CREATE_ALBUM");
		String createTitle = properties.getProperty("CREATE_TITLE");
		
		try {
			Class.forName(driver);
			con = DriverManager.getConnection(url, user, password);
			stm = con.createStatement();
			stm.executeQuery(createStyle + createArtist + createAlbum + createTitle);
			
		} catch(ClassNotFoundException e){
			JOptionPane.showMessageDialog(null, "Classe nao encontrada");
			e.printStackTrace();
		} catch(SQLException e) { 
			JOptionPane.showMessageDialog(null, "Excessão SQL");
			e.printStackTrace();
		} finally {
			try {
				stm.execute("SHUTDOWN");
				con.close();
			} catch(SQLException onConClose) {
				JOptionPane.showMessageDialog(null, "Houve erro no fechamento da conexão");
				onConClose.printStackTrace();
			}
		}
	}
	
	public void deleteDBFiles() {
		try {
			File[] dbFiles = new File(dbHome).listFiles();
			for(int i = 0; i < dbFiles.length; i++) {
				dbFiles[i].delete();
			}
		} catch(SecurityException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		DBLayer db = DBLayer.getInstance();
		db.createDB();
		db.insertDB();
		db.getTableData("SELECT * FROM ARTIST ORDER BY descr");
	}
}
_fs

Outra dica: PreparedStatements com a mesma query foram criados para serem reaproveitados. Portanto você só precisa declará-los antes de entrar nos laços:

String insertStyle = properties.getProperty("INSERT_STYLE");  
String insertArtist = properties.getProperty("INSERT_ARTIST");  

PreparedStatement insertStyleStatement  = con.prepareStatement(insertStyle);  
PreparedStatement insertArtistStatement  = con.prepareStatement(insertArtist );  

for( ... ) {
    insertStyleStatement.setString( 1, "test style" );
    insertStyleStatement.addBatch();
    for( ... ) {
        insertArtistStatement.setString( 1, "test artist" );
        insertArtistStatement.addBatch();
    }
}

// e depois de processar tudo
insertStyleStatement.executeBatch();
insertArtistStatement.executeBatch();
rafaelveggi

Você já teve algum problema semelhante?
Acho estranho o fato de não acusar violação de integridade, pois cada for entra na hierarquia do banco, e usa chaves estrangeiras
Parece que ele simplesmente se esquece de algumas linhas…

rafaelveggi

Olha só o que eu encontrei…
http://sourceforge.net/forum/message.php?msg_id=3779616

rafaelveggi

RESOLVIDO!
Este realmente é um bug do HSQLDB 1.8 em relação ao sync de disco.
Para resolver o problema, apenas coloquei as seguintes linhas antes do meu primeiro preparedStatement

PreparedStatement pstmArtist = con.prepareStatement("SET WRITE_DELAY 0");
pstmArtist.executeUpdate();
pstmArtist.close();

Obrigado, LIPE

Criado 20 de dezembro de 2007
Ultima resposta 20 de dez. de 2007
Respostas 6
Participantes 2