Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seção 31: Acesso a Banco de Dados com JDBC #52

Open
JayCesar opened this issue Apr 3, 2024 · 5 comments
Open

Seção 31: Acesso a Banco de Dados com JDBC #52

JayCesar opened this issue Apr 3, 2024 · 5 comments

Comments

@JayCesar
Copy link
Owner

JayCesar commented Apr 3, 2024

Intro:
JDBC.pdf

@JayCesar
Copy link
Owner Author

JayCesar commented Apr 3, 2024

Conexão com o banco:

Passos:
image

Obs: é necessário baixar o Connector J:
https://dev.mysql.com/downloads/connector/j/

Logo após baixar ele, eu preciso criar uma pasta onde salvo bibliotecas externas ao Java. Em seguida no Eclipse eu adiciono essa biblioteca ao projeto. Pronto, conectei a bilbioteca!


Conectar com o banco de dados no JDBC é instanciar um objeto do tipo Connection:

Código:

private static Connection conn = null;
	
	// Método para conectar com o banco de dados:
	public static Connection getConnection() {
		if(conn == null) {
			
			try {
				Properties props = loadProperties();
				String url = props.getProperty("dburl");
				conn = DriverManager.getConnection(url, props);
				System.out.println("Conexão feita!");
			}
			catch(SQLException e) {
				throw new DbException(e.getMessage());
			}
			
		}
		return conn;
	}
	
	// Método para fechar a conexão
	public static void closeConnection() {
		if (conn != null) {
			try {
				conn.close();
			} catch(SQLException e) {
				throw new DbException(e.getMessage());
			}
		}
	}

	
	// Método para carregaras propriedades:
	private static Properties loadProperties() {
		try (FileInputStream fs = new FileInputStream("db.properties")){
			Properties props = new Properties();
			props.load(fs);
			// esse props.load(fs) vai fazer a leitura do arquivo properties apontadado pelo meu InputStreamFs e vai guardar os dados dentro do objeto props
			return props;
		}catch (IOException e) {
			throw new DbException(e.getMessage());
		}
			
	}

Conectando Intellij + MySql:
https://www.jetbrains.com/help/idea/connecting-to-a-database.html

@JayCesar
Copy link
Owner Author

JayCesar commented Apr 4, 2024

Demo: recuperar dados

Classe Statment
Serve para montar um comando SQL para ser executado;
Eu instancio ela usando uma variável do tipo Connection

Classe ResultSet
Representa um objeto contendo o resultado da consulta em foram de tabela.
Por padrão ele começa na posição zero! Para percorrer a tabela eu devo usar o método next();
Para acessar um campo eu posso usar

System.out.println(rs.getInt("Id"));
// Pega o inteiro que está lá no campo Id da tabela;

Ele possui operação para posicionar na tabela;
image
Slide completo:
image


Código:

public class program {

	public static void main(String[] args) {
		
		// São recursos externos não controlados pela JVM que eu preciso fechar
		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		
		try{
			conn = DB.getConnection();
			
			st = conn.createStatement();
	
			rs = st.executeQuery("Select * from department");
			
			while(rs.next()) {
				System.out.println(rs.getInt("Id") + ", " + rs.getString("name"));
			}
		}catch(SQLException e){
			e.printStackTrace();
		}
		finally {
			DB.closeResultSet(rs); // rs.close() Pode lançar uma exceção 
			DB.closeStatement(st); // sc.close() Pode lançar uma exceção 
			DB.closeConnection();
		}
		
	}
}

@JayCesar
Copy link
Owner Author

JayCesar commented Apr 4, 2024

Inserir Dados

Class PreparedStatement
Deixa montar a consulta SQL deixando os parâmetros para colocar depois.
Dessa forma, usando '?' como place holder:

	Connection conn = null;
		PreparedStatement st = null;
		try {
			conn = DB.getConnection();
			st = conn.prepareStatement(
					"INSERT INTO seller"
					+ "(Name, Email, BirthDate, BaseSalary, DepartmentId)"
					+ "VALUES" 
					+ "(?, ?, ?, ?, ?)"
					);
		}

Quando eu for mexer com data com JDBC eu DEVO utilizar o new java.sql.Date(0))
Ficaria assim:

st.setDate(3, new java.sql.Date(sdf.parse("22/04/1985").getTime()));

Agora o código completo com anotações:

public class program {

	public static void main(String[] args) {
		
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		
		Connection conn = null;
		PreparedStatement st = null;
		
		try {
			conn = DB.getConnection();
			st = conn.prepareStatement(
					"INSERT INTO seller"
					+ "(Name, Email, BirthDate, BaseSalary, DepartmentId)"
					+ "VALUES" 
					+ "(?, ?, ?, ?, ?)",
					Statement.RETURN_GENERATED_KEYS); // fazendo isso eu retorno o ID da nova informação qeu adicionei
			st.setString(1, "Carl Purple");
			st.setString(2, "[email protected]");
			st.setDate(3, new java.sql.Date(sdf.parse("22/04/1985").getTime()));
			st.setDouble(4, 3000.0);
			st.setInt(5, 4);
			
			// Para executar o comando:
			int rowsAffected = st.executeUpdate();
			// Quando é uma oepração em que eu vou alterar os dados eu utilizo update
			// O resultado dessa operação é um número inteiro indicando quantas linhas foram alteradas
		
			if(rowsAffected > 0) {
				// st.getGeneratedKeys(); retorna um objeto do tipo ResultSet
				ResultSet rs = st.getGeneratedKeys(); // E pode ter mais de um valor
				while(rs.next()) {
					int id = rs.getInt(1); // Assim indico que quero o valor da primeria coluna, pois estamos inserindo apenas um
					System.out.println("Done! Id = " + id);
				}
			}else {
				System.out.println("No Rows affected!");
			}
			
			// 
		}catch (SQLException e) {
			e.printStackTrace();
		}catch(ParseException e) {
			e.printStackTrace();
		}finally{
			DB.closeStatement(st);
			DB.closeConnection();
		}
		
	}

}

@JayCesar
Copy link
Owner Author

JayCesar commented Apr 4, 2024

Deletar Dados

É muito comum que aconteça um problema de integridade referencial, por isso criamos um exceção personalizada:
DbIntegrityException

Por exemplo, se eu tentar apagar um id que é uma chave estrangeira em outra tabela, por exemplo, um departamento que possua vendedores atrelados a ele. Isso que é um problema de integridade referencial.

Por isso precisamos cria uma exceção personalizada.

Código:
Obs: na aula ele apagou um ID que não estava atrelado a ninguém, caso eu queira apagar algum que esteja, irá lançar essa exceção que eu criei.

public static void main(String[] args) {
		
			Connection conn = null;
			
			PreparedStatement st = null;
			
			try {
				conn = DB.getConnection();
				st = conn.prepareStatement(
						"DELETE FROM department"
						+ "WHERE"
						+ "Id = ?");
				
				st.setInt(1, 2);
				// Não vou conseguir apagar porque esse id está atrelado a outra tabela
			
				int rowsAffected = st.executeUpdate();
				
				System.out.println("Done! Rows affected: " + rowsAffected);
			}catch(SQLException e) {
				throw new DbIntegrityException(e.getMessage());
			} 
			finally {
				DB.closeStatement(st);
				DB.closeConnection();
			}
		
	}

@JayCesar
Copy link
Owner Author

JayCesar commented Apr 4, 2024

Transações

Transação é uma operação que deve manter a consistência dos dadso
A transação tem que ser atômica (acontece tudo ou nada)
Tem que ser consistente (isolada e durável)
Tem que ser isolada
Tem que ser durável
Ex: transação de dinheiro.
image


Para implementar transações eu utilizo 3 métodos:

  • setAutoCommit(false);
  • commit
  • rollback()

setAutoCommit(false);

Serve para dizer que cada operação isolada será confirmada isoladamente, se eu passar true como argumento!

commit()

Serve para confirmar a a transação

rollback()

Significa desfazer o que já foi feito até o momento. Ou seja, se tiver alguma falha na transação, basta eu chamar o rollack. Assim volto ao estado em que eu estava e garanto a integridade.


Fake Error:

	int rows1 = st.executeUpdate("UPDATE seller SET BaseSalary = 2090 WHERE DepartmentId = 1");
			
	int x = 1;
	if (x < 2) throw new SQLException("Fake Error");
				
	int rows2 = st.executeUpdate("UPDATE seller SET BaseSalary = 3090 WHERE DepartmentId = 2");

A ideia é usar as operações para tratar erros parecidos com esse, ou seja, que ocorrem no meio do caminho.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant