InterBase w Spring Boot

  • Post author:
  • Post category:Java

Spring Boot dostarcza mechanizm szablonów Jdbc Templates, z wykorzystaniem których możemy w miarę wygodnie operować na bazach Sql ciągle pozostając na poziomie zapytań SQL.

Aby skorzystać z tej funkcjonalności dodaj zależność Spring Data JDBC.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

Pierwszy problem na jaki napotykamy przy próbie podłączenia się do baz InterBase to brak klienta JDBC w Maven Repository. Najlepszym rozwiązaniem będzie dodanie go do lokalnego repozytorium Mavena. Musisz oczywiście mieć zainstalowany klient lub serwer InterBase.

mvn install:install-file 
  -Dfile="c:\Program Files\Embarcadero\InterBase\SDK\lib\interclient.jar" 
  -DgroupId=com.embarcadero -DartifactId=interclient 
  -Dversion=12.0.0 
  -Dpackaging=jar 
  -DgeneratePom=true

Możemy teraz dodać zależność do pom.xml

<dependency>
    <groupId>com.embarcadero</groupId>
    <artifactId>interclient</artifactId>
    <version>12.0.0</version>
</dependency>

Dodajmy teraz klasę konfiguracyjną połączenie z bazą danych

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class Config {

    @Value("${target.database}")
    private String database;

    @Value("${target.server}")
    private String server;

    @Value("${target.charset}")
    private String charset;

    @Value("${target.port}")
    private String port;

    @Value("${target.username}")
    private String username;

    @Value("${target.password}")
    private String password;

    @Bean
    public DataSource interbaseDataSource() {
        interbase.interclient.DataSource dataSource = new interbase.interclient.DataSource();
        dataSource.setDatabaseName(database);
        dataSource.setServerName(server);
        dataSource.setCharSet(charset);
        dataSource.setPortNumber(Integer.parseInt(port));
        dataSource.setUser(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

Spring Data JDBC wymaga jeszcze informacji o dialekcie, dodajmy więc klasę konfiguracyjną:

@Configuration
public class SpringDataJdbcConfiguration extends AbstractJdbcConfiguration {

    @Override
    public Dialect jdbcDialect(NamedParameterJdbcOperations operations) {
        return AnsiDialect.INSTANCE;
    }
}

Parametry połączenia ustawiamy w pliku application.properties

target.server=127.0.0.1
target.port=3050
target.charset=Cp1250
target.database=c:\\Users\\All Users\\Application Data\\Embarcadero\\InterBase\\gds_db\\examples\\database\\employee.gdb
target.username=sysdba
target.password=masterkey

spring.jpa.database-platform=org.hibernate.dialect.InterbaseDialect
hibernate.dialect=org.hibernate.dialect.InterbaseDialect

Pobierzmy dane z tabeli pracowników bazy employee.gdb

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import pl.bilansjr.jdbctemplates.demo.domain.Employee;
import pl.bilansjr.jdbctemplates.demo.domain.EmployeeRowMapper;

import java.util.List;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    private static final String SELECT_COUNT_EMPLOYEE = "SELECT COUNT(*) FROM EMPLOYEE";
    private static final String SELECT_ALL_EMPLOYEE = "SELECT * FROM EMPLOYEE";
    private static final String SELECT_ALL_EMPLOYEE_WITH_FIELD_ALIAS = "SELECT EMP_NO AS ID, FIRST_NAME, LAST_NAME, SALARY FROM EMPLOYEE";

    final JdbcTemplate jdbcTemplate;

    public DemoApplication(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        Integer employeeCount = jdbcTemplate.queryForObject(SELECT_COUNT_EMPLOYEE, Integer.class);
        System.out.println(employeeCount);
      
    }
}

Spróbujmy teraz wczytać wszystkich pracowników. Stwórzmy encję Employee:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    private Integer id;
    private String firstName;
    private String lastName;
    private BigDecimal salary;
}

oraz mapper, który wykorzystamy podczas tworzenia obiektów Employee

import org.springframework.jdbc.core.RowMapper;

import java.sql.ResultSet;
import java.sql.SQLException;

public class EmployeeRowMapper implements RowMapper {
    @Override
    public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
        Employee employee = new Employee();
        employee.setId(rs.getInt("EMP_NO"));
        employee.setFirstName(rs.getString("FIRST_NAME"));
        employee.setLastName(rs.getString("LAST_NAME"));
        employee.setSalary(rs.getBigDecimal("SALARY"));
        return employee;
    }
}

Wczytajmy pracowników do listy List<Employee>

String sql = SELECT_ALL_EMPLOYEE;
List employees = jdbcTemplate.query(sql, new EmployeeRowMapper());
employees.forEach(System.out::println);

Możemy również obejść się bez definiowania mappera

employees = jdbcTemplate.query(SELECT_ALL_EMPLOYEE_WITH_FIELD_ALIAS, 
  new BeanPropertyRowMapper(Employee.class));
employees.forEach(System.out::println);

Jak widzisz, aby skorzystać z BeanPropertyRowMapper musimy uzyskać zgodność kolumn tabeli z polami encji. W tym celu kolumnę EMP_NO identyfikujemy jako ID.

SELECT EMP_NO AS ID, FIRST_NAME, LAST_NAME, SALARY FROM EMPLOYEE