Skip to content

Commit

Permalink
# entities refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Przemeo committed Apr 20, 2024
1 parent 7309c7f commit 41e1b40
Show file tree
Hide file tree
Showing 24 changed files with 500 additions and 488 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# no-orm-allowed

Comparison of different libraries used for querying SQL databases.
Comparison of different libraries used for querying SQL databases.

Run `mvn clean install` to build app. \
Run `docker compose up` to start Postgres instance. \
Run `mvn quarkus:dev` to start app with `dev` profile. \
Run `mvn quarkus:run -Dquarkus.profile=prod` to start app with `prod` profile.
3 changes: 1 addition & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>${p6spy.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.database-rider</groupId>
Expand Down Expand Up @@ -401,7 +400,7 @@
<jdbcUrl>${db.url}</jdbcUrl>
<jdbcUser>${db.username}</jdbcUser>
<jdbcPassword>${db.password}</jdbcPassword>
<tableNamePattern>first_entity,second_entity,additional_attribute,another_entity</tableNamePattern>
<tableNamePattern>company,worker,additional_attribute,animal</tableNamePattern>
<packageName>no.orm.allowed.entity.sql</packageName>
<targetFolder>${project.basedir}/target/generated-sources/querydsl/sql</targetFolder>
<namePrefix>SQ</namePrefix>
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/no/orm/allowed/control/Repository.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package no.orm.allowed.control;

import no.orm.allowed.entity.jpa.SecondEntityAttributes;
import no.orm.allowed.entity.jpa.WorkerAttributes;

import java.util.Collection;
import java.util.List;
Expand All @@ -9,13 +9,13 @@

public interface Repository {

List<Long> getIsObsoleteAndCitySortedAnotherEntityIds(String animalPrefix,
long skip,
long limit);
List<Long> getIsDangerousAndNatureSortedAnimalIds(String namePrefix,
long skip,
long limit);

List<String> getDistinctSecondEntityNames(long firstEntityId);
List<String> getDistinctWorkerDescriptions(long companyId);

Optional<SecondEntityAttributes> getSecondEntityAttributes(long secondEntityId);
Optional<WorkerAttributes> getWorkerAttributes(long workerId);

long getDistinctAttributeValuesCount(Collection<String> attributeNames);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ public class CriteriaJPARepository implements Repository {

@Override
@Transactional
public List<Long> getIsObsoleteAndCitySortedAnotherEntityIds(@Nonnull String animalPrefix,
long skip,
long limit) {
public List<Long> getIsDangerousAndNatureSortedAnimalIds(@Nonnull String namePrefix,
long skip,
long limit) {
Session session = entityManager.unwrap(Session.class);
HibernateCriteriaBuilder builder = session.getCriteriaBuilder();

CriteriaQuery<Tuple> query = builder.createTupleQuery();
Root<AnotherEntity> root = query.from(AnotherEntity.class);
Root<Animal> root = query.from(Animal.class);

query.multiselect(root.get(AnotherEntity_.id), root.get(AnotherEntity_.isObsolete), root.get(AnotherEntity_.city))
.where(builder.like(root.get(AnotherEntity_.animal), animalPrefix + "%"))
.orderBy(builder.desc(root.get(AnotherEntity_.isObsolete)), builder.asc(root.get(AnotherEntity_.city)));
query.multiselect(root.get(Animal_.id), root.get(Animal_.isDangerous), root.get(Animal_.nature))
.where(builder.like(root.get(Animal_.name), namePrefix + "%"))
.orderBy(builder.desc(root.get(Animal_.isDangerous)), builder.asc(root.get(Animal_.nature)));

return session.createQuery(query)
.setFirstResult(Long.valueOf(skip).intValue())
Expand All @@ -62,16 +62,16 @@ public List<Long> getIsObsoleteAndCitySortedAnotherEntityIds(@Nonnull String ani

@Override
@Transactional
public List<String> getDistinctSecondEntityNames(long firstEntityId) {
public List<String> getDistinctWorkerDescriptions(long companyId) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
EntityGraph<FirstEntity> entityGraph = entityManager.createEntityGraph(FirstEntity.class);
entityGraph.addSubgraph(FirstEntity_.secondEntities);
EntityGraph<Company> entityGraph = entityManager.createEntityGraph(Company.class);
entityGraph.addSubgraph(Company_.workers);

CriteriaQuery<String> query = builder.createQuery(String.class);
Root<FirstEntity> root = query.from(FirstEntity.class);
Root<Company> root = query.from(Company.class);

query.select(root.join(FirstEntity_.secondEntities, JoinType.INNER).get(SecondEntity_.name))
.where(builder.equal(root.get(FirstEntity_.id), firstEntityId))
query.select(root.join(Company_.workers, JoinType.INNER).get(Worker_.description))
.where(builder.equal(root.get(Company_.id), companyId))
.distinct(true);

return entityManager.createQuery(query)
Expand All @@ -81,18 +81,18 @@ public List<String> getDistinctSecondEntityNames(long firstEntityId) {

@Override
@Transactional
public Optional<SecondEntityAttributes> getSecondEntityAttributes(long secondEntityId) {
public Optional<WorkerAttributes> getWorkerAttributes(long workerId) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();

CriteriaQuery<SecondEntityAttributes> query = builder.createQuery(SecondEntityAttributes.class);
Root<SecondEntity> root = query.from(SecondEntity.class);
CriteriaQuery<WorkerAttributes> query = builder.createQuery(WorkerAttributes.class);
Root<Worker> root = query.from(Worker.class);

Selection<SecondEntityAttributes> selection = builder.construct(SecondEntityAttributes.class,
root.get(SecondEntity_.name),
root.join(SecondEntity_.typeAttribute, JoinType.LEFT).get(AdditionalAttribute_.attributeValue),
root.join(SecondEntity_.colorAttribute, JoinType.LEFT).get(AdditionalAttribute_.attributeValue));
Selection<WorkerAttributes> selection = builder.construct(WorkerAttributes.class,
root.get(Worker_.description),
root.join(Worker_.nameAttribute, JoinType.LEFT).get(AdditionalAttribute_.attributeValue),
root.join(Worker_.favouriteColorAttribute, JoinType.LEFT).get(AdditionalAttribute_.attributeValue));
query.select(selection)
.where(builder.equal(root.get(SecondEntity_.id), builder.literal(secondEntityId)));
.where(builder.equal(root.get(Worker_.id), builder.literal(workerId)));

return findSingleResult(entityManager.createQuery(query));
}
Expand Down
40 changes: 20 additions & 20 deletions src/main/java/no/orm/allowed/control/hql/HQLRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import jakarta.persistence.Tuple;
import jakarta.transaction.Transactional;
import no.orm.allowed.control.Repository;
import no.orm.allowed.entity.jpa.FirstEntity_;
import no.orm.allowed.entity.jpa.SecondEntityAttributes;
import no.orm.allowed.entity.jpa.Company_;
import no.orm.allowed.entity.jpa.WorkerAttributes;
import org.hibernate.Session;

import java.util.Collection;
Expand All @@ -30,17 +30,17 @@ public class HQLRepository implements Repository {

@Override
@Transactional
public List<Long> getIsObsoleteAndCitySortedAnotherEntityIds(@Nonnull String animalPrefix,
long skip,
long limit) {
public List<Long> getIsDangerousAndNatureSortedAnimalIds(@Nonnull String namePrefix,
long skip,
long limit) {
Session session = entityManager.unwrap(Session.class);
String appendedAnimalPrefix = animalPrefix + "%";
String appendedNamePrefix = namePrefix + "%";

return session.createSelectionQuery("SELECT ae.id, ae.isObsolete, ae.city " +
"FROM AnotherEntity ae " +
"WHERE ae.animal LIKE :animalPrefix " +
"ORDER BY ae.isObsolete DESC, ae.city", Tuple.class)
.setParameter("animalPrefix", appendedAnimalPrefix)
return session.createSelectionQuery("SELECT a.id, a.isDangerous, a.nature " +
"FROM Animal a " +
"WHERE a.name LIKE :namePrefix " +
"ORDER BY a.isDangerous DESC, a.nature", Tuple.class)
.setParameter("namePrefix", appendedNamePrefix)
.setFirstResult(Long.valueOf(skip).intValue())
.setMaxResults(Long.valueOf(limit).intValue())
.stream()
Expand All @@ -50,23 +50,23 @@ public List<Long> getIsObsoleteAndCitySortedAnotherEntityIds(@Nonnull String ani

@Override
@Transactional
public List<String> getDistinctSecondEntityNames(long firstEntityId) {
public List<String> getDistinctWorkerDescriptions(long companyId) {
Session session = entityManager.unwrap(Session.class);

//Can also be written as: SELECT DISTINCT se.name FROM FirstEntity fe INNER JOIN SecondEntity se ON fk(se.firstEntity) = fe.id WHERE fe.id = (:id)
return FirstEntity_.getDistinctSecondEntityNames(session, firstEntityId);
//Can also be written as: SELECT DISTINCT w.description FROM Company c INNER JOIN Worker w ON fk(w.company) = c.id WHERE c.id = (:id)
return Company_.getDistinctWorkerDescriptions(session, companyId);
}

@Override
@Transactional
public Optional<SecondEntityAttributes> getSecondEntityAttributes(long secondEntityId) {
public Optional<WorkerAttributes> getWorkerAttributes(long workerId) {
Session session = entityManager.unwrap(Session.class);

return session.createSelectionQuery("SELECT new no.orm.allowed.entity.jpa.SecondEntityAttributes(se.name, typeAttribute.attributeValue, colorAttribute.attributeValue) " +
"FROM SecondEntity se " +
"LEFT OUTER JOIN se.typeAttribute typeAttribute " +
"LEFT OUTER JOIN se.colorAttribute colorAttribute " +
"WHERE se.id = " + secondEntityId, SecondEntityAttributes.class)
return session.createSelectionQuery("SELECT new no.orm.allowed.entity.jpa.WorkerAttributes(w.description, nameAttribute.attributeValue, favouriteColorAttribute.attributeValue) " +
"FROM Worker w " +
"LEFT OUTER JOIN w.nameAttribute nameAttribute " +
"LEFT OUTER JOIN w.favouriteColorAttribute favouriteColorAttribute " +
"WHERE w.id = " + workerId, WorkerAttributes.class)
//Limit related to the use of uniqueResultOptional method
.setMaxResults(LIMIT_VALUE)
.uniqueResultOptional();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/no/orm/allowed/control/jdbi/JdbiDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
public interface JdbiDAO {

//Since 6.3.0.Final Hibernate supports similar DAO-style mechanism with use of HQL: https://in.relation.to/2023/08/31/orm-630/
@SqlQuery("SELECT DISTINCT SECOND_ENTITY.NAME FROM FIRST_ENTITY INNER JOIN SECOND_ENTITY ON SECOND_ENTITY.FIRST_ENTITY_ID = FIRST_ENTITY.ID WHERE FIRST_ENTITY.ID = (:id)")
List<String> getDistinctSecondEntityNames(@Bind("id") long firstEntityId);
@SqlQuery("SELECT DISTINCT WORKER.DESCRIPTION FROM COMPANY INNER JOIN WORKER ON WORKER.COMPANY_ID = COMPANY.ID WHERE COMPANY.ID = (:id)")
List<String> getDistinctWorkerDescriptions(@Bind("id") long companyId);

}
44 changes: 22 additions & 22 deletions src/main/java/no/orm/allowed/control/jdbi/JdbiRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
import no.orm.allowed.control.Repository;
import no.orm.allowed.entity.jpa.SecondEntityAttributes;
import no.orm.allowed.entity.jpa.WorkerAttributes;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.core.generic.GenericType;
import org.jdbi.v3.core.mapper.reflect.ConstructorMapper;
Expand All @@ -27,19 +27,19 @@ public class JdbiRepository implements Repository {

@Override
@Transactional
public List<Long> getIsObsoleteAndCitySortedAnotherEntityIds(@Nonnull String animalPrefix,
long skip,
long limit) {
String appendedAnimalPrefix = animalPrefix + "%";
public List<Long> getIsDangerousAndNatureSortedAnimalIds(@Nonnull String namePrefix,
long skip,
long limit) {
String appendedNamePrefix = namePrefix + "%";

return jdbi.withHandle(handle ->
handle.createQuery("SELECT ANOTHER_ENTITY.ID, ANOTHER_ENTITY.IS_OBSOLETE, ANOTHER_ENTITY.CITY " +
"FROM ANOTHER_ENTITY " +
"WHERE ANOTHER_ENTITY.ANIMAL LIKE :animalPrefix " +
"ORDER BY ANOTHER_ENTITY.IS_OBSOLETE DESC, ANOTHER_ENTITY.CITY " +
handle.createQuery("SELECT ANIMAL.ID, ANIMAL.IS_DANGEROUS, ANIMAL.NATURE " +
"FROM ANIMAL " +
"WHERE ANIMAL.NAME LIKE :namePrefix " +
"ORDER BY ANIMAL.IS_DANGEROUS DESC, ANIMAL.NATURE " +
"OFFSET :skip " +
"FETCH FIRST :limit ROWS ONLY")
.bind("animalPrefix", appendedAnimalPrefix)
.bind("namePrefix", appendedNamePrefix)
.bind("skip", skip)
.bind("limit", limit)
.map(result -> result.getColumn("ID", Long.class))
Expand All @@ -49,25 +49,25 @@ public List<Long> getIsObsoleteAndCitySortedAnotherEntityIds(@Nonnull String ani

@Override
@Transactional
public List<String> getDistinctSecondEntityNames(long firstEntityId) {
return jdbi.withExtension(JdbiDAO.class, dao -> dao.getDistinctSecondEntityNames(firstEntityId));
public List<String> getDistinctWorkerDescriptions(long companyId) {
return jdbi.withExtension(JdbiDAO.class, dao -> dao.getDistinctWorkerDescriptions(companyId));
}

@Override
@Transactional
public Optional<SecondEntityAttributes> getSecondEntityAttributes(long secondEntityId) {
public Optional<WorkerAttributes> getWorkerAttributes(long workerId) {
return jdbi.withHandle(handle -> {
handle.registerRowMapper(ConstructorMapper.factory(SecondEntityAttributes.class));
return handle.createQuery("SELECT SECOND_ENTITY.NAME, typeAttribute.ATTRIBUTE_VALUE typeAttributeValue, colorAttribute.ATTRIBUTE_VALUE colorAttributeValue " +
"FROM SECOND_ENTITY " +
"LEFT OUTER JOIN ADDITIONAL_ATTRIBUTE typeAttribute " +
"ON typeAttribute.ATTRIBUTE_NAME = 'type' AND typeAttribute.SECOND_ENTITY_ID = SECOND_ENTITY.ID " +
"LEFT OUTER JOIN ADDITIONAL_ATTRIBUTE colorAttribute " +
"ON colorAttribute.ATTRIBUTE_NAME = 'color' AND colorAttribute.SECOND_ENTITY_ID = SECOND_ENTITY.ID " +
"WHERE SECOND_ENTITY.ID = " + secondEntityId + " " +
handle.registerRowMapper(ConstructorMapper.factory(WorkerAttributes.class));
return handle.createQuery("SELECT WORKER.DESCRIPTION, nameAttribute.ATTRIBUTE_VALUE nameAttributeValue, favouriteColorAttribute.ATTRIBUTE_VALUE favouriteColorAttributeValue " +
"FROM WORKER " +
"LEFT OUTER JOIN ADDITIONAL_ATTRIBUTE nameAttribute " +
"ON nameAttribute.ATTRIBUTE_NAME = 'name' AND nameAttribute.WORKER_ID = WORKER.ID " +
"LEFT OUTER JOIN ADDITIONAL_ATTRIBUTE favouriteColorAttribute " +
"ON favouriteColorAttribute.ATTRIBUTE_NAME = 'favouriteColor' AND favouriteColorAttribute.WORKER_ID = WORKER.ID " +
"WHERE WORKER.ID = " + workerId + " " +
//Limit related to the use of findOne method
"FETCH FIRST 2 ROWS ONLY")
.mapTo(SecondEntityAttributes.class)
.mapTo(WorkerAttributes.class)
.findOne();
});
}
Expand Down
Loading

0 comments on commit 41e1b40

Please sign in to comment.