-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add alternative implementations with JPA and JDBC
- Loading branch information
Ralf Ueberfuhr
committed
Aug 30, 2024
1 parent
1603a26
commit 389000a
Showing
10 changed files
with
529 additions
and
48 deletions.
There are no files selected for viewing
232 changes: 232 additions & 0 deletions
232
...provider/src/main/java/de/samples/schulung/quarkus/persistence/CustomersSinkJdbcImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
package de.samples.schulung.quarkus.persistence; | ||
|
||
import de.samples.schulung.quarkus.domain.Customer; | ||
import de.samples.schulung.quarkus.domain.Customer.CustomerState; | ||
import de.samples.schulung.quarkus.domain.CustomersSink; | ||
import io.quarkus.arc.properties.IfBuildProperty; | ||
import jakarta.enterprise.context.ApplicationScoped; | ||
import jakarta.enterprise.inject.Typed; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
import javax.sql.DataSource; | ||
import java.sql.*; | ||
import java.time.LocalDate; | ||
import java.util.Collection; | ||
import java.util.LinkedList; | ||
import java.util.Optional; | ||
import java.util.UUID; | ||
import java.util.stream.Stream; | ||
|
||
@ApplicationScoped | ||
@Typed(CustomersSink.class) | ||
@RequiredArgsConstructor | ||
@IfBuildProperty( | ||
name = "persistence.sink.implementation", | ||
stringValue = "jdbc" | ||
) | ||
public class CustomersSinkJdbcImpl implements CustomersSink { | ||
|
||
private final DataSource ds; | ||
|
||
/* ******************************************************* * | ||
* Converter methods - could be converter objects instead * | ||
* ******************************************************* */ | ||
|
||
private static UUID convertUuid(String uuid) { | ||
return Optional.ofNullable(uuid) | ||
.map(UUID::fromString) | ||
.orElse(null); | ||
} | ||
|
||
private static String convertUuid(UUID uuid) { | ||
return Optional.ofNullable(uuid) | ||
.map(UUID::toString) | ||
.orElse(null); | ||
} | ||
|
||
private static LocalDate convertDate(Date date) { | ||
return Optional.ofNullable(date) | ||
.map(Date::toLocalDate) | ||
.orElse(null); | ||
} | ||
|
||
private static Date convertDate(LocalDate date) { | ||
return Optional.ofNullable(date) | ||
.map(Date::valueOf) | ||
.orElse(null); | ||
} | ||
|
||
private static CustomerState convertState(int value) { | ||
return CustomerState.values()[value]; | ||
} | ||
|
||
private static int convertState(CustomerState value) { | ||
return Optional.ofNullable(value) | ||
.map(CustomerState::ordinal) | ||
.orElse(0); | ||
|
||
} | ||
|
||
/* ******************************************************* * | ||
* Row Mapping - could be a RowMapper object instead * | ||
* ******************************************************* */ | ||
|
||
private static Customer readSingle(ResultSet rs) throws SQLException { | ||
return Customer.builder() | ||
.uuid(convertUuid(rs.getString("UUID"))) | ||
.birthday(convertDate(rs.getDate("BIRTH_DATE"))) | ||
.name(rs.getString("NAME")) | ||
.state(convertState(rs.getInt("STATE"))) | ||
.build(); | ||
} | ||
|
||
private static Stream<Customer> readAll(ResultSet rs) throws SQLException { | ||
Collection<Customer> result = new LinkedList<>(); | ||
while (rs.next()) { | ||
result.add(readSingle(rs)); | ||
} | ||
return result.stream(); | ||
} | ||
|
||
/* ******************************************************* * | ||
* CustomersSink implementation * | ||
* ******************************************************* */ | ||
|
||
@Override | ||
public Stream<Customer> findAll() { | ||
try (Connection con = ds.getConnection(); | ||
Statement stmt = con.createStatement(); | ||
ResultSet rs = stmt.executeQuery( | ||
"select * from CUSTOMERS" | ||
)) { | ||
|
||
return readAll(rs); | ||
|
||
} catch (SQLException e) { | ||
throw new RuntimeException(e); // eigene Exception? | ||
} | ||
} | ||
|
||
@Override | ||
public Stream<Customer> findByState(CustomerState state) { | ||
try (Connection con = ds.getConnection(); | ||
PreparedStatement stmt = con.prepareStatement( | ||
"select * from CUSTOMERS where STATE=?" | ||
)) { | ||
|
||
stmt.setInt(1, convertState(state)); | ||
|
||
try (ResultSet rs = stmt.executeQuery()) { | ||
return readAll(rs); | ||
} | ||
|
||
} catch (SQLException e) { | ||
throw new RuntimeException(e); // eigene Exception? | ||
} | ||
} | ||
|
||
@Override | ||
public Optional<Customer> findByUuid(UUID uuid) { | ||
try (Connection con = ds.getConnection(); | ||
PreparedStatement stmt = con.prepareStatement( | ||
"select * from CUSTOMERS where UUID=?" | ||
)) { | ||
|
||
stmt.setString(1, convertUuid(uuid)); | ||
|
||
try (ResultSet rs = stmt.executeQuery()) { | ||
if (!rs.next()) { | ||
return Optional.empty(); | ||
} | ||
return Optional.of(readSingle(rs)); | ||
} | ||
|
||
} catch (SQLException e) { | ||
throw new RuntimeException(e); // eigene Exception? | ||
} | ||
} | ||
|
||
@Override | ||
public void insert(Customer customer) { | ||
try (Connection con = ds.getConnection(); | ||
PreparedStatement stmt = con.prepareStatement( | ||
"insert into CUSTOMERS(NAME,BIRTH_DATE,STATE) values(?,?,?)", | ||
Statement.RETURN_GENERATED_KEYS | ||
)) { | ||
|
||
stmt.setString(1, customer.getName()); | ||
stmt.setDate(2, convertDate(customer.getBirthday())); | ||
stmt.setInt(3, convertState(customer.getState())); | ||
stmt.executeUpdate(); | ||
|
||
try (ResultSet rs = stmt.getGeneratedKeys()) { | ||
if (!rs.next()) { | ||
throw new RuntimeException("not expected"); // bessere Exception | ||
} | ||
customer.setUuid(convertUuid(rs.getString(1))); | ||
} | ||
|
||
} catch (SQLException e) { | ||
throw new RuntimeException(e); // eigene Exception? | ||
} | ||
} | ||
|
||
@Override | ||
public void update(Customer customer) { | ||
try (Connection con = ds.getConnection(); | ||
PreparedStatement stmt = con.prepareStatement( | ||
"update CUSTOMERS set NAME=?, BIRTH_DATE=?, STATE=?) where UUID=?", | ||
Statement.RETURN_GENERATED_KEYS | ||
)) { | ||
|
||
stmt.setString(1, customer.getName()); | ||
stmt.setDate(2, convertDate(customer.getBirthday())); | ||
stmt.setInt(3, convertState(customer.getState())); | ||
stmt.setString(4, convertUuid(customer.getUuid())); | ||
stmt.executeUpdate(); | ||
|
||
try (ResultSet rs = stmt.getGeneratedKeys()) { | ||
if (!rs.next()) { | ||
throw new RuntimeException("not expected"); // bessere Exception | ||
} | ||
customer.setUuid(convertUuid(rs.getString(1))); | ||
} | ||
|
||
} catch (SQLException e) { | ||
throw new RuntimeException(e); // eigene Exception? | ||
} | ||
} | ||
|
||
@Override | ||
public boolean delete(UUID uuid) { | ||
try (Connection con = ds.getConnection(); | ||
PreparedStatement stmt = con.prepareStatement( | ||
"delete from CUSTOMERS where UUID=?" | ||
)) { | ||
|
||
stmt.setString(1, convertUuid(uuid)); | ||
return stmt.executeUpdate() > 0; | ||
|
||
} catch (SQLException e) { | ||
throw new RuntimeException(e); // eigene Exception? | ||
} | ||
} | ||
|
||
@Override | ||
public long count() { | ||
try (Connection con = ds.getConnection(); | ||
Statement stmt = con.createStatement(); | ||
ResultSet rs = stmt.executeQuery( | ||
"select count(uuid) from CUSTOMERS" | ||
)) { | ||
|
||
if (!rs.next()) { | ||
return 0; | ||
} | ||
return rs.getLong(1); | ||
|
||
} catch (SQLException e) { | ||
throw new RuntimeException(e); // eigene Exception? | ||
} | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
...-provider/src/main/java/de/samples/schulung/quarkus/persistence/CustomersSinkJpaImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package de.samples.schulung.quarkus.persistence; | ||
|
||
import de.samples.schulung.quarkus.domain.Customer; | ||
import de.samples.schulung.quarkus.domain.CustomersSink; | ||
import io.quarkus.arc.properties.IfBuildProperty; | ||
import jakarta.enterprise.context.ApplicationScoped; | ||
import jakarta.enterprise.inject.Typed; | ||
import jakarta.persistence.EntityManager; | ||
import jakarta.transaction.Transactional; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
import java.util.Optional; | ||
import java.util.UUID; | ||
import java.util.stream.Stream; | ||
|
||
@ApplicationScoped | ||
@Typed(CustomersSink.class) | ||
@RequiredArgsConstructor | ||
@IfBuildProperty( | ||
name = "persistence.sink.implementation", | ||
stringValue = "jpa" | ||
) | ||
public class CustomersSinkJpaImpl implements CustomersSink { | ||
|
||
private final CustomerEntityMapper mapper; | ||
private final EntityManager em; | ||
|
||
@Override | ||
public Stream<Customer> findAll() { | ||
return em.createQuery( | ||
"select c from Customer c", | ||
CustomerEntity.class | ||
) | ||
.getResultList() | ||
.stream() | ||
.map(mapper::map); | ||
} | ||
|
||
@Override | ||
public Stream<Customer> findByState(Customer.CustomerState state) { | ||
return em.createQuery( | ||
"select c from Customer c where c.state = :state", | ||
CustomerEntity.class | ||
) | ||
.setParameter("state", state) | ||
.getResultList() | ||
.stream() | ||
.map(mapper::map); | ||
} | ||
|
||
@Override | ||
public Optional<Customer> findByUuid(UUID uuid) { | ||
return Optional | ||
.ofNullable(em.find(CustomerEntity.class, uuid)) | ||
.map(mapper::map); | ||
} | ||
|
||
@Transactional | ||
@Override | ||
public void insert(Customer customer) { | ||
var entity = this.mapper.map(customer); | ||
em.persist(entity); | ||
mapper.copy(entity, customer); | ||
} | ||
|
||
@Transactional | ||
@Override | ||
public void update(Customer customer) { | ||
var entity = this.mapper.map(customer); | ||
em.persist(entity); | ||
mapper.copy(entity, customer); | ||
} | ||
|
||
@Transactional | ||
@Override | ||
public boolean delete(UUID uuid) { | ||
var found = em.find(CustomerEntity.class, uuid); | ||
if (found == null) { | ||
return false; | ||
} | ||
em.remove(found); | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean existsByUuid(UUID uuid) { | ||
var found = em.find(CustomerEntity.class, uuid); | ||
return found != null; | ||
} | ||
|
||
@Override | ||
public long count() { | ||
return 0; // TODO ?? | ||
} | ||
} |
Oops, something went wrong.