Skip to content

Commit

Permalink
Add alternative implementations with JPA and JDBC
Browse files Browse the repository at this point in the history
  • Loading branch information
Ralf Ueberfuhr committed Aug 30, 2024
1 parent 1603a26 commit 389000a
Show file tree
Hide file tree
Showing 10 changed files with 529 additions and 48 deletions.
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?
}
}
}
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 ??
}
}
Loading

0 comments on commit 389000a

Please sign in to comment.