Refactor repository layer using Jakarta Data

Replaced custom repository logic with Jakarta Data interfaces to reduce boilerplate and enhance compile-time query validation. Removed `AbstractRepository` and introduced `TransactionRunner` for consistent transactional support. Updated all repository facades to delegate query operations to generated interfaces while retaining the same API, ensuring backward compatibility. Added dependencies for `jakarta.data-api` and Hibernate's `hibernate-processor` for annotation-based query generation. Verified functional parity and improved testability across the repository layer.
This commit is contained in:
anthorob committed 2026-09-25 12:48:48 -04:00
1 parent 677b3f8013
commit bceab4b2b9
16 files changed
+604 -230

No files matched your search

@@ -1,95 +0,0 @@
package me.bobert.netneutrality.db;
/*
* Copyright (c) anthorob
*
* https://discord.gg/qUa6zNFZsd
*/
import jakarta.persistence.criteria.CriteriaQuery;
import org.hibernate.Session;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Generic, constructor-injected Hibernate repository.
*
* <p>All work runs through Hibernate's native {@code fromSession}/{@code fromTransaction}/
* {@code inTransaction} helpers, which open and close the session and commit or roll back the
* transaction. Exceptions are never swallowed: a failed write is rolled back and rethrown.
*
* @param <T> the entity type
* @param <ID> the entity identifier type
*/
public abstract class AbstractRepository<T, ID> {
protected final SessionProvider sessions;
private final Class<T> type;
protected AbstractRepository(SessionProvider sessions, Class<T> type) {
this.sessions = Objects.requireNonNull(sessions, "sessions");
this.type = Objects.requireNonNull(type, "type");
}
protected Class<T> type() {
return type;
}
public List<T> findAll() {
return read(session -> {
CriteriaQuery<T> query = session.getCriteriaBuilder().createQuery(type);
query.from(type);
return session.createSelectionQuery(query).getResultList();
});
}
public Optional<T> findById(ID id) {
Objects.requireNonNull(id, "id");
return read(session -> Optional.ofNullable(session.find(type, id)));
}
/**
* Inserts or updates the entity.
*
* @param entity the entity to save
* @return the persistent (merged) state, which callers should use from then on
*/
public T save(T entity) {
Objects.requireNonNull(entity, "entity");
return write(session -> session.merge(entity));
}
/**
* Deletes the entity with the given id, if it exists.
*
* @param id the identifier
* @return {@code true} if a row was deleted
*/
public boolean deleteById(ID id) {
Objects.requireNonNull(id, "id");
return write(session -> {
T entity = session.find(type, id);
if (entity == null) {
return false;
}
session.remove(entity);
return true;
});
}
protected <R> R read(Function<Session, R> work) {
return sessions.getSessionFactory().fromSession(work);
}
protected <R> R write(Function<Session, R> work) {
return sessions.getSessionFactory().fromTransaction(work);
}
protected void writeVoid(Consumer<Session> work) {
sessions.getSessionFactory().inTransaction(work);
}
}
@@ -0,0 +1,35 @@
package me.bobert.netneutrality.db;
/*
* Copyright (c) anthorob
*
* https://discord.gg/qUa6zNFZsd
*/
import org.hibernate.StatelessSession;
import java.util.Objects;
import java.util.function.Function;
/**
* Runs work on a Hibernate {@link StatelessSession}, the session type used by the generated
* Jakarta Data repositories.
*
* <p>{@link #inTx(Function)} commits on success and rolls back and rethrows on failure.
*/
public class TransactionRunner {
private final SessionProvider sessions;
public TransactionRunner(SessionProvider sessions) {
this.sessions = Objects.requireNonNull(sessions, "sessions");
}
public <R> R read(Function<StatelessSession, R> work) {
return sessions.getSessionFactory().fromStatelessSession(work);
}
public <R> R inTx(Function<StatelessSession, R> work) {
return sessions.getSessionFactory().fromStatelessTransaction(work);
}
}
@@ -0,0 +1,27 @@
package me.bobert.netneutrality.db.data;
/*
* Copyright (c) anthorob
*
* https://discord.gg/qUa6zNFZsd
*/
import jakarta.data.repository.CrudRepository;
import jakarta.data.repository.Query;
import jakarta.data.repository.Repository;
import me.bobert.netneutrality.db.entities.OBlacklist;
import java.util.List;
@Repository
public interface BlacklistQueries extends CrudRepository<OBlacklist, Integer> {
@Query("from OBlacklist where guild.guildId = :guildId order by id")
List<OBlacklist> byGuild(String guildId);
@Query("select word from OBlacklist where guild.guildId = :guildId and enabled = true")
List<String> enabledWords(String guildId);
@Query("from OBlacklist where upper(word) = upper(:word) and guild.guildId = :guildId")
List<OBlacklist> findWord(String guildId, String word);
}
@@ -0,0 +1,15 @@
package me.bobert.netneutrality.db.data;
/*
* Copyright (c) anthorob
*
* https://discord.gg/qUa6zNFZsd
*/
import jakarta.data.repository.CrudRepository;
import jakarta.data.repository.Repository;
import me.bobert.netneutrality.db.entities.OGuild;
@Repository
public interface GuildQueries extends CrudRepository<OGuild, String> {
}
@@ -0,0 +1,24 @@
package me.bobert.netneutrality.db.data;
/*
* Copyright (c) anthorob
*
* https://discord.gg/qUa6zNFZsd
*/
import jakarta.data.repository.CrudRepository;
import jakarta.data.repository.Query;
import jakarta.data.repository.Repository;
import me.bobert.netneutrality.db.entities.OGuildSetting;
import java.util.List;
@Repository
public interface GuildSettingQueries extends CrudRepository<OGuildSetting, Integer> {
@Query("from OGuildSetting where guild.guildId = :guildId")
List<OGuildSetting> byGuild(String guildId);
@Query("from OGuildSetting where guild.guildId = :guildId and upper(name) = upper(:name)")
List<OGuildSetting> byName(String guildId, String name);
}
@@ -0,0 +1,30 @@
package me.bobert.netneutrality.db.data;
/*
* Copyright (c) anthorob
*
* https://discord.gg/qUa6zNFZsd
*/
import jakarta.data.Limit;
import jakarta.data.repository.CrudRepository;
import jakarta.data.repository.Find;
import jakarta.data.repository.Query;
import jakarta.data.repository.Repository;
import me.bobert.netneutrality.db.entities.OLogMessage;
import java.util.List;
import java.util.Optional;
@Repository
public interface MessageQueries extends CrudRepository<OLogMessage, Integer> {
@Find
Optional<OLogMessage> byMessageId(String messageId);
@Query("delete from OLogMessage where messageId = :messageId")
int deleteByMessageId(String messageId);
@Query("from OLogMessage where guild.guildId = :guildId and userId = :userId order by dateSent desc")
List<OLogMessage> byUser(String userId, String guildId, Limit limit);
}
@@ -0,0 +1,25 @@
package me.bobert.netneutrality.db.data;
/*
* Copyright (c) anthorob
*
* https://discord.gg/qUa6zNFZsd
*/
import jakarta.data.repository.CrudRepository;
import jakarta.data.repository.Find;
import jakarta.data.repository.Query;
import jakarta.data.repository.Repository;
import me.bobert.netneutrality.db.entities.OTask;
import java.util.Optional;
@Repository
public interface TaskQueries extends CrudRepository<OTask, Integer> {
@Find
Optional<OTask> byTaskId(String taskId);
@Query("delete from OTask where taskId = :taskId")
int deleteByTaskId(String taskId);
}
@@ -14,8 +14,6 @@ import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Table;
import org.hibernate.Hibernate;
@@ -23,9 +21,6 @@ import java.util.Objects;
@Entity
@Table(name = "guild_settings")
@NamedQueries({
@NamedQuery(name = "settings_findByName", query = "select o from OGuildSetting o where o.guild.id = :id and upper(o.name) = upper(:name)")
})
public class OGuildSetting {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -6,17 +6,19 @@ package me.bobert.netneutrality.db.repository;
* https://discord.gg/qUa6zNFZsd
*/
import me.bobert.netneutrality.db.AbstractRepository;
import me.bobert.netneutrality.db.SessionProvider;
import me.bobert.netneutrality.db.TransactionRunner;
import me.bobert.netneutrality.db.data.BlacklistQueries_;
import me.bobert.netneutrality.db.entities.OBlacklist;
import me.bobert.netneutrality.db.entities.OGuild;
import org.hibernate.Session;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
public class BlacklistRepository extends AbstractRepository<OBlacklist, Integer> {
public class BlacklistRepository {
/**
* Outcome of {@link #enableWord(String, String, String)}.
@@ -30,23 +32,18 @@ public class BlacklistRepository extends AbstractRepository<OBlacklist, Integer>
UNCHANGED
}
private final TransactionRunner tx;
public BlacklistRepository(SessionProvider sessions) {
super(sessions, OBlacklist.class);
this.tx = new TransactionRunner(sessions);
}
public List<OBlacklist> findByGuildId(String guildId) {
return read(session -> session
.createSelectionQuery("FROM OBlacklist o WHERE o.guild.guildId = :guildId ORDER BY o.id", OBlacklist.class)
.setParameter("guildId", guildId)
.getResultList());
return tx.read(session -> new BlacklistQueries_(session).byGuild(guildId));
}
public Set<String> findEnabledWords(String guildId) {
return read(session -> session
.createSelectionQuery("SELECT o.word FROM OBlacklist o WHERE o.guild.guildId = :guildId AND o.enabled = true", String.class)
.setParameter("guildId", guildId)
.getResultStream()
.collect(Collectors.toUnmodifiableSet()));
return tx.read(session -> Set.copyOf(new BlacklistQueries_(session).enabledWords(guildId)));
}
/**
@@ -59,26 +56,33 @@ public class BlacklistRepository extends AbstractRepository<OBlacklist, Integer>
* @return what changed
*/
public EnableOutcome enableWord(String guildId, String creatorId, String word) {
return write(session -> {
List<OBlacklist> existing = findWord(session, guildId, word);
return tx.inTx(session -> {
BlacklistQueries_ queries = new BlacklistQueries_(session);
List<OBlacklist> existing = queries.findWord(guildId, word);
if (existing.isEmpty()) {
OGuild guild = new OGuild();
guild.setGuildId(guildId);
OBlacklist blacklist = new OBlacklist();
blacklist.setGuild(session.getReference(OGuild.class, guildId));
blacklist.setGuild(guild);
blacklist.setCreatorId(creatorId);
blacklist.setWord(word);
blacklist.setEnabled(true);
session.persist(blacklist);
queries.insert(blacklist);
return EnableOutcome.CREATED;
}
boolean changed = false;
List<OBlacklist> changed = new ArrayList<>();
for (OBlacklist blacklist : existing) {
if (!Boolean.TRUE.equals(blacklist.getEnabled())) {
blacklist.setEnabled(true);
changed = true;
changed.add(blacklist);
}
}
return changed ? EnableOutcome.ENABLED : EnableOutcome.UNCHANGED;
if (changed.isEmpty()) {
return EnableOutcome.UNCHANGED;
}
queries.updateAll(changed);
return EnableOutcome.ENABLED;
});
}
@@ -90,18 +94,50 @@ public class BlacklistRepository extends AbstractRepository<OBlacklist, Integer>
* @return {@code true} if at least one row was deleted
*/
public boolean deleteWord(String guildId, String word) {
return write(session -> {
List<OBlacklist> existing = findWord(session, guildId, word);
existing.forEach(session::remove);
return tx.inTx(session -> {
BlacklistQueries_ queries = new BlacklistQueries_(session);
List<OBlacklist> existing = queries.findWord(guildId, word);
queries.deleteAll(existing);
return !existing.isEmpty();
});
}
private static List<OBlacklist> findWord(Session session, String guildId, String word) {
return session
.createSelectionQuery("FROM OBlacklist o WHERE upper(o.word) = upper(:word) AND o.guild.guildId = :guildId", OBlacklist.class)
.setParameter("guildId", guildId)
.setParameter("word", word)
.getResultList();
public List<OBlacklist> findAll() {
return tx.read(session -> new BlacklistQueries_(session).findAll().toList());
}
public Optional<OBlacklist> findById(Integer id) {
Objects.requireNonNull(id, "id");
return tx.read(session -> new BlacklistQueries_(session).findById(id));
}
/**
* Inserts or updates the entity.
*
* @param entity the entity to save
* @return the saved state, which callers should use from then on
*/
public OBlacklist save(OBlacklist entity) {
Objects.requireNonNull(entity, "entity");
return tx.inTx(session -> new BlacklistQueries_(session).save(entity));
}
/**
* Deletes the entity with the given id, if it exists.
*
* @param id the identifier
* @return {@code true} if a row was deleted
*/
public boolean deleteById(Integer id) {
Objects.requireNonNull(id, "id");
return tx.inTx(session -> {
BlacklistQueries_ queries = new BlacklistQueries_(session);
return queries.findById(id)
.map(entity -> {
queries.delete(entity);
return true;
})
.orElse(false);
});
}
}
@@ -6,14 +6,21 @@ package me.bobert.netneutrality.db.repository;
* https://discord.gg/qUa6zNFZsd
*/
import me.bobert.netneutrality.db.AbstractRepository;
import me.bobert.netneutrality.db.SessionProvider;
import me.bobert.netneutrality.db.TransactionRunner;
import me.bobert.netneutrality.db.data.GuildQueries_;
import me.bobert.netneutrality.db.entities.OGuild;
public class GuildRepository extends AbstractRepository<OGuild, String> {
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public class GuildRepository {
private final TransactionRunner tx;
public GuildRepository(SessionProvider sessions) {
super(sessions, OGuild.class);
this.tx = new TransactionRunner(sessions);
}
/**
@@ -23,14 +30,52 @@ public class GuildRepository extends AbstractRepository<OGuild, String> {
* @return the persistent guild
*/
public OGuild findOrCreate(String guildId) {
return write(session -> {
OGuild guild = session.find(OGuild.class, guildId);
if (guild == null) {
guild = new OGuild();
return tx.inTx(session -> {
GuildQueries_ queries = new GuildQueries_(session);
return queries.findById(guildId).orElseGet(() -> {
OGuild guild = new OGuild();
guild.setGuildId(guildId);
session.persist(guild);
}
return guild;
return queries.insert(guild);
});
});
}
public List<OGuild> findAll() {
return tx.read(session -> new GuildQueries_(session).findAll().toList());
}
public Optional<OGuild> findById(String id) {
Objects.requireNonNull(id, "id");
return tx.read(session -> new GuildQueries_(session).findById(id));
}
/**
* Inserts or updates the entity.
*
* @param entity the entity to save
* @return the saved state, which callers should use from then on
*/
public OGuild save(OGuild entity) {
Objects.requireNonNull(entity, "entity");
return tx.inTx(session -> new GuildQueries_(session).save(entity));
}
/**
* Deletes the entity with the given id, if it exists.
*
* @param id the identifier
* @return {@code true} if a row was deleted
*/
public boolean deleteById(String id) {
Objects.requireNonNull(id, "id");
return tx.inTx(session -> {
GuildQueries_ queries = new GuildQueries_(session);
return queries.findById(id)
.map(entity -> {
queries.delete(entity);
return true;
})
.orElse(false);
});
}
}
@@ -6,25 +6,27 @@ package me.bobert.netneutrality.db.repository;
* https://discord.gg/qUa6zNFZsd
*/
import me.bobert.netneutrality.db.AbstractRepository;
import me.bobert.netneutrality.db.GSettings;
import me.bobert.netneutrality.db.SessionProvider;
import me.bobert.netneutrality.db.TransactionRunner;
import me.bobert.netneutrality.db.data.GuildSettingQueries_;
import me.bobert.netneutrality.db.entities.OGuild;
import me.bobert.netneutrality.db.entities.OGuildSetting;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public class GuildSettingRepository extends AbstractRepository<OGuildSetting, Integer> {
public class GuildSettingRepository {
private final TransactionRunner tx;
public GuildSettingRepository(SessionProvider sessions) {
super(sessions, OGuildSetting.class);
this.tx = new TransactionRunner(sessions);
}
public List<OGuildSetting> findByGuild(String guildId) {
return read(session -> session
.createSelectionQuery("FROM OGuildSetting o WHERE o.guild.guildId = :guildId", OGuildSetting.class)
.setParameter("guildId", guildId)
.getResultList());
return tx.read(session -> new GuildSettingQueries_(session).byGuild(guildId));
}
/**
@@ -36,27 +38,67 @@ public class GuildSettingRepository extends AbstractRepository<OGuildSetting, In
* @param value the new value, or {@code null} to reset
*/
public void upsertOrDelete(String guildId, GSettings setting, String value) {
writeVoid(session -> {
List<OGuildSetting> existing = session
.createNamedSelectionQuery("settings_findByName", OGuildSetting.class)
.setParameter("id", guildId)
.setParameter("name", setting.getName())
.getResultList();
tx.inTx(session -> {
GuildSettingQueries_ queries = new GuildSettingQueries_(session);
List<OGuildSetting> existing = queries.byName(guildId, setting.getName());
if (value == null || setting.getDefaultValue().equals(value)) {
existing.forEach(session::remove);
return;
queries.deleteAll(existing);
return null;
}
if (existing.isEmpty()) {
OGuild guild = new OGuild();
guild.setGuildId(guildId);
OGuildSetting guildSetting = new OGuildSetting();
guildSetting.setGuild(session.getReference(OGuild.class, guildId));
guildSetting.setGuild(guild);
guildSetting.setName(setting.getName());
guildSetting.setValue(value);
session.persist(guildSetting);
queries.insert(guildSetting);
} else {
existing.forEach(guildSetting -> guildSetting.setValue(value));
queries.updateAll(existing);
}
return null;
});
}
public List<OGuildSetting> findAll() {
return tx.read(session -> new GuildSettingQueries_(session).findAll().toList());
}
public Optional<OGuildSetting> findById(Integer id) {
Objects.requireNonNull(id, "id");
return tx.read(session -> new GuildSettingQueries_(session).findById(id));
}
/**
* Inserts or updates the entity.
*
* @param entity the entity to save
* @return the saved state, which callers should use from then on
*/
public OGuildSetting save(OGuildSetting entity) {
Objects.requireNonNull(entity, "entity");
return tx.inTx(session -> new GuildSettingQueries_(session).save(entity));
}
/**
* Deletes the entity with the given id, if it exists.
*
* @param id the identifier
* @return {@code true} if a row was deleted
*/
public boolean deleteById(Integer id) {
Objects.requireNonNull(id, "id");
return tx.inTx(session -> {
GuildSettingQueries_ queries = new GuildSettingQueries_(session);
return queries.findById(id)
.map(entity -> {
queries.delete(entity);
return true;
})
.orElse(false);
});
}
}
@@ -6,20 +6,24 @@ package me.bobert.netneutrality.db.repository;
* https://discord.gg/qUa6zNFZsd
*/
import me.bobert.netneutrality.db.AbstractRepository;
import jakarta.data.Limit;
import me.bobert.netneutrality.db.SessionProvider;
import me.bobert.netneutrality.db.TransactionRunner;
import me.bobert.netneutrality.db.data.MessageQueries_;
import me.bobert.netneutrality.db.entities.OGuild;
import me.bobert.netneutrality.db.entities.OLogMessage;
import org.hibernate.Session;
import java.time.Instant;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public class MessageRepository extends AbstractRepository<OLogMessage, Integer> {
public class MessageRepository {
private final TransactionRunner tx;
public MessageRepository(SessionProvider sessions) {
super(sessions, OLogMessage.class);
this.tx = new TransactionRunner(sessions);
}
/**
@@ -34,21 +38,22 @@ public class MessageRepository extends AbstractRepository<OLogMessage, Integer>
* @return the persistent log entry
*/
public OLogMessage log(String guildId, String channelId, String userId, String messageId, String content, Instant sentAt) {
return write(session -> {
return tx.inTx(session -> {
OGuild guild = new OGuild();
guild.setGuildId(guildId);
OLogMessage logMessage = new OLogMessage();
logMessage.setGuild(session.getReference(OGuild.class, guildId));
logMessage.setGuild(guild);
logMessage.setChannelId(channelId);
logMessage.setUserId(userId);
logMessage.setMessageId(messageId);
logMessage.setMessage(content == null ? null : content.trim());
logMessage.setDateSent(sentAt);
session.persist(logMessage);
return logMessage;
return new MessageQueries_(session).insert(logMessage);
});
}
public Optional<OLogMessage> findByMessageId(String messageId) {
return read(session -> findByMessageId(session, messageId));
return tx.read(session -> new MessageQueries_(session).byMessageId(messageId));
}
public Optional<String> findMessageContent(String messageId) {
@@ -63,19 +68,20 @@ public class MessageRepository extends AbstractRepository<OLogMessage, Integer>
* @return {@code true} if the message was found and updated
*/
public boolean updateEditedMessage(String messageId, String newMessage) {
return write(session -> findByMessageId(session, messageId)
.map(message -> {
message.setEditedMessage(newMessage);
return true;
})
.orElse(false));
return tx.inTx(session -> {
MessageQueries_ queries = new MessageQueries_(session);
return queries.byMessageId(messageId)
.map(message -> {
message.setEditedMessage(newMessage);
queries.update(message);
return true;
})
.orElse(false);
});
}
public boolean deleteByMessageId(String messageId) {
return write(session -> session
.createMutationQuery("DELETE FROM OLogMessage o WHERE o.messageId = :messageId")
.setParameter("messageId", messageId)
.executeUpdate() > 0);
return tx.inTx(session -> new MessageQueries_(session).deleteByMessageId(messageId) > 0);
}
/**
@@ -87,18 +93,45 @@ public class MessageRepository extends AbstractRepository<OLogMessage, Integer>
* @return the messages
*/
public List<OLogMessage> findByUser(String userId, String guildId, int max) {
return read(session -> session
.createSelectionQuery("FROM OLogMessage o WHERE o.guild.guildId = :guildId AND o.userId = :userId ORDER BY o.dateSent DESC", OLogMessage.class)
.setParameter("guildId", guildId)
.setParameter("userId", userId)
.setMaxResults(max)
.getResultList());
return tx.read(session -> new MessageQueries_(session).byUser(userId, guildId, Limit.of(max)));
}
private static Optional<OLogMessage> findByMessageId(Session session, String messageId) {
return session
.createSelectionQuery("FROM OLogMessage o WHERE o.messageId = :messageId", OLogMessage.class)
.setParameter("messageId", messageId)
.uniqueResultOptional();
public List<OLogMessage> findAll() {
return tx.read(session -> new MessageQueries_(session).findAll().toList());
}
public Optional<OLogMessage> findById(Integer id) {
Objects.requireNonNull(id, "id");
return tx.read(session -> new MessageQueries_(session).findById(id));
}
/**
* Inserts or updates the entity.
*
* @param entity the entity to save
* @return the saved state, which callers should use from then on
*/
public OLogMessage save(OLogMessage entity) {
Objects.requireNonNull(entity, "entity");
return tx.inTx(session -> new MessageQueries_(session).save(entity));
}
/**
* Deletes the entity with the given id, if it exists.
*
* @param id the identifier
* @return {@code true} if a row was deleted
*/
public boolean deleteById(Integer id) {
Objects.requireNonNull(id, "id");
return tx.inTx(session -> {
MessageQueries_ queries = new MessageQueries_(session);
return queries.findById(id)
.map(entity -> {
queries.delete(entity);
return true;
})
.orElse(false);
});
}
}
@@ -6,21 +6,25 @@ package me.bobert.netneutrality.db.repository;
* https://discord.gg/qUa6zNFZsd
*/
import me.bobert.netneutrality.db.AbstractRepository;
import me.bobert.netneutrality.db.SessionProvider;
import me.bobert.netneutrality.db.TransactionRunner;
import me.bobert.netneutrality.db.data.TaskQueries_;
import me.bobert.netneutrality.db.entities.OTask;
import org.hibernate.Session;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public class TaskRepository extends AbstractRepository<OTask, Integer> {
public class TaskRepository {
private final TransactionRunner tx;
public TaskRepository(SessionProvider sessions) {
super(sessions, OTask.class);
this.tx = new TransactionRunner(sessions);
}
public Optional<OTask> findByTaskId(String taskId) {
return read(session -> findByTaskId(session, taskId));
return tx.read(session -> new TaskQueries_(session).byTaskId(taskId));
}
/**
@@ -32,32 +36,62 @@ public class TaskRepository extends AbstractRepository<OTask, Integer> {
* @return the persistent task
*/
public OTask upsert(String taskId, String typeId, String payload) {
return write(session -> {
OTask task = findByTaskId(session, taskId).orElse(null);
if (task == null) {
task = new OTask();
task.setTaskId(taskId);
task.setTaskClass(typeId);
task.setPayload(payload);
session.persist(task);
} else {
return tx.inTx(session -> {
TaskQueries_ queries = new TaskQueries_(session);
Optional<OTask> existing = queries.byTaskId(taskId);
if (existing.isPresent()) {
OTask task = existing.get();
task.setPayload(payload);
return queries.update(task);
}
return task;
OTask task = new OTask();
task.setTaskId(taskId);
task.setTaskClass(typeId);
task.setPayload(payload);
return queries.insert(task);
});
}
public boolean deleteByTaskId(String taskId) {
return write(session -> session
.createMutationQuery("DELETE FROM OTask o WHERE o.taskId = :taskId")
.setParameter("taskId", taskId)
.executeUpdate() > 0);
return tx.inTx(session -> new TaskQueries_(session).deleteByTaskId(taskId) > 0);
}
private static Optional<OTask> findByTaskId(Session session, String taskId) {
return session
.createSelectionQuery("FROM OTask o WHERE o.taskId = :taskId", OTask.class)
.setParameter("taskId", taskId)
.uniqueResultOptional();
public List<OTask> findAll() {
return tx.read(session -> new TaskQueries_(session).findAll().toList());
}
public Optional<OTask> findById(Integer id) {
Objects.requireNonNull(id, "id");
return tx.read(session -> new TaskQueries_(session).findById(id));
}
/**
* Inserts or updates the entity.
*
* @param entity the entity to save
* @return the saved state, which callers should use from then on
*/
public OTask save(OTask entity) {
Objects.requireNonNull(entity, "entity");
return tx.inTx(session -> new TaskQueries_(session).save(entity));
}
/**
* Deletes the entity with the given id, if it exists.
*
* @param id the identifier
* @return {@code true} if a row was deleted
*/
public boolean deleteById(Integer id) {
Objects.requireNonNull(id, "id");
return tx.inTx(session -> {
TaskQueries_ queries = new TaskQueries_(session);
return queries.findById(id)
.map(entity -> {
queries.delete(entity);
return true;
})
.orElse(false);
});
}
}