Mengenal class java.sql.Statement
Hi, setelah kita membuat connection, menyiapkan database schema dengan menggunakan flyway database migration. Sekarang kita akan mengambil data dari table yang ada di database. Tapi sebelum itu ada beberapa yang harus kita siapkan karena disini saya menggunakan Design pattern. Nah temen-temen mungkin binggung apa itu design pattern ya khan?…
Ok design pattern in software engineering simple wordnya itu solusi untuk meminimalisir duplication (menulis hal yang sama dengan satu tujuan). tapi gak usah di pusingin dulu perlahan-lahan dengan pengalan menulis koding dan memahami isinya pasti nanti akan paham dengan sendirinya.
Back to topic, seperti yang saya katakan tadi saya mau membuat sebuah interface dulu sebagai template dengan nama CrudRepository
yang saya simpan di package com.maryanto.dimas.bootcamp.dao
seperti berikut:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.maryanto.dimas.bootcamp.dao;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;
public interface CrudRepository<T, ID> {
public T save(T value) throws SQLException;
public T update(T value) throws SQLException;
public Boolean removeById(ID value) throws SQLException;
public Optional<T> findById(ID value) throws SQLException;
public List<T> findAll() throws SQLException;
public List<T> findAll(Long start, Long limit, Long orderIndex, String orderDirection, T param) throws SQLException;
}
Ok setelah itu kita buat kelas baru dengan nama ExampleTable
yang di simpan di package com.maryanto.dimas.bootcamp.entity
seperti berikut:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.maryanto.dimas.bootcamp.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Timestamp;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExampleTable {
private String id;
private String name;
private Date createdDate;
private Timestamp createdTime;
private Boolean active;
private Long counter;
private BigDecimal currency;
private String description;
private Float floating;
}
Jadi class ExampleTable
tersebut merepresentasikan columns yang ada pada table example_table
pada database bootcamp
. ok tahap selanjutnya adalah kita membuat repository / Data Access Object atau singkatannya DAO. buat kelas dengan nama ExampleTableDao
pada package com.maryanto.dimas.dao
seperti berikut:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.maryanto.dimas.bootcamp.dao;
import com.maryanto.dimas.bootcamp.entity.ExampleTable;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class ExampleTableDao implements CrudRepository<ExampleTable, String> {
private Connection connection;
public ExampleTableDao(Connection connection) {
this.connection = connection;
}
@Override
public List<ExampleTable> findAll() throws SQLException {
List<ExampleTable> list = new ArrayList<>();
//language=PostgreSQL
String query = "select id as id,\n" +
" name as name,\n" +
" created_date as createdDate,\n" +
" created_time as createdTime,\n" +
" is_active as active,\n" +
" counter as counter,\n" +
" currency as currency,\n" +
" description as description,\n" +
" floating as floating\n" +
"from example_table";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
while (resultSet.next()) {
ExampleTable data = new ExampleTable(
resultSet.getString("id"),
resultSet.getString("name"),
resultSet.getDate("createdDate"),
resultSet.getTimestamp("createdTime"),
resultSet.getObject("active", Boolean.class),
resultSet.getLong("counter"),
resultSet.getBigDecimal("currency"),
resultSet.getString("description"),
resultSet.getFloat("floating")
);
list.add(data);
}
resultSet.close();
statement.close();
return list;
}
// other method goes here
}
Nah jadi dari sample koding diatas, itu kita melakukan execute query sebagai berikut:
select id as id,
name as name,
created_date as createdDate,
created_time as createdTime,
is_active as active,
counter as counter,
currency as currency,
description as description,
floating as floating
from example_table
yang di simpan dalam kelas String kemudian di execute menggunakan API class java.sql.Statement
. perintah menggunakan API class Statement
biasanya digunakan untuk query yang tidak membutuhkan parameter / argument contohnya query seperti berikut:
select id as id,
name as name,
created_date as createdDate,
created_time as createdTime,
is_active as active,
counter as counter,
currency as currency,
description as description,
floating as floating
from example_table
where id = '001'
Nah dengan query tersebut klo misalnya nilai id = '001'
bernilai statis itu tidak jadi masalah, tetapi jika nilainya bisa ber-ubah-ubah sebaiknya jangan menggunakan API class Statement
. Terkadang saya menemukan koding yang klo di tulis di dengan menggunakan JDBC seperti berikut:
import java.sql.*;
public class ExampleYangSalah {
public ExampleTable findById(String id) throws SQLException {
// ini adalah contoh yang salah
String query = "select id as id,\n" +
" name as name,\n" +
" created_date as createdDate,\n" +
" created_time as createdTime,\n" +
" is_active as active,\n" +
" counter as counter,\n" +
" currency as currency,\n" +
" description as description,\n" +
" floating as floating\n" +
"from example_table\n" +
"where id = '" + id + "'";
}
}
}
Nah kenapa saya bilang salah, karena ini bisa kena serangan yang namanya SQL Injection. buat yang belum paham silahkan baca di sini. Akan lebih baik jika kita menggunakan object PreparedStatement
.
Ok dan yang terakhir sekarang kita buat unit testing untuk method findAll()
tersebut dengan cara membuat class di folder src/test/java/
dengan nama TestIntegrationExampleTable
dalam package com.maryanto.dimas.bootcamp
seperti berikut:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.maryanto.dimas.bootcamp;
import com.maryanto.dimas.bootcamp.config.DatasourceConfig;
import com.maryanto.dimas.bootcamp.dao.ExampleTableDao;
import com.maryanto.dimas.bootcamp.entity.ExampleTable;
import junit.framework.TestCase;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
@Slf4j
public class TestIntegrationExampleTable extends TestCase {
private DataSource dataSource;
private ExampleTableDao dao;
@Override
protected void setUp() throws Exception {
this.dataSource = new DatasourceConfig().getDataSource();
}
@Test
public void testFindAllData() {
try (Connection connection = this.dataSource.getConnection()) {
this.dao = new ExampleTableDao(connection);
List<ExampleTable> list = this.dao.findAll();
assertEquals("jumlah data example table", list.size(), 5);
} catch (SQLException ex) {
log.error("can't fetch data", ex);
}
}
}
Kemudian jalankan perintah test seperti berikut:
mvn clean test
dan berikut hasilnya:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.maryanto.dimas.bootcamp.TestConnection
[main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
[main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
[main] INFO com.maryanto.dimas.bootcamp.TestConnection - status connected
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.364 sec
Running com.maryanto.dimas.bootcamp.TestIntegrationExampleTable
[main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-2 - Starting...
[main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-2 - Start completed.
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.077 sec
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.642 s
[INFO] Finished at: 2020-04-20T19:00:17+07:00
[INFO] ------------------------------------------------------------------------
Yuk simak juga videonya,
Dan jika temen-temen belajar hal baru kali ini jangan lupa buat Like, Subcribe, dan Share ke temen kalian. Terimakasih!!!
-
Referensi
https://github.com/dimMaryanto93/jdbc-psql-example
https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html
https://id.wikipedia.org/wiki/Injeksi_SQL
https://en.wikipedia.org/wiki/Software_design_pattern#Creational_patterns
https://en.wikipedia.org/wiki/Dependency_injection
https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
https://www.oracle.com/technetwork/java/dataaccessobject-138824.html