Hibernate integration-test for entity mapping - java

I'm using hibernate with critera builing queries and specification pattern.
My interface:
public interface Specification<T> {
Criterion toCriteria();
}
Implementations looks like:
Restrictions.eq("someField", "value");
My goal is to test that my enity class has "someField" with exact name.
At this time i have hibernate integration test and it covers problem at some point, but obviously unit-test for reflection fields should be separeted.
I will be grateful for the suggestions on the solution.

Related

Use proxies with Hibernate runtime bytecode enhancement

I'm using Spring Boot 2.7.5 with Hibernate 5.6.12.Final and apply bytecode enhancement at build-time via hibernate-enhance-maven-plugin. It works great and prevents eagerly fetching #OneToOne relationships, as described here https://vladmihalcea.com/hibernate-lazytoone-annotation/.
However, I found that all lazy relationships do not use proxies anymore but are fetched from the database when I use the getter (which has been instrumented by the maven plugin at build time). Basically, what I would like to do is to still use proxies with bytecode enhancement. Something similar is available at runtime https://in.relation.to/2019/07/30/bytecode-proxy/, but I can't find a way to do it at build-time.
For a bit of context, I need proxies for lazy-loaded properties because it allows me to apply custom logic in entity->dto mapper (using Mapstruct) based on whether the proxy has been initialized or not. In some cases, I must trigger an initialization manually if a Hibernate session is available (and prevent LazyInitializationException).
Any suggestion is greatly appreciated!
If you want to avoid LazyInitializationException for your DTO mapping, you should rather try to avoid doing the mapping in Java code and instead use a solution that can take the mapping down to the HQL/SQL level.
I think this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for a possible use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(User.class)
public interface UserDto {
#IdMapping
Long getId();
String getName();
Set<RoleDto> getRoles();
#EntityView(Role.class)
interface RoleDto {
#IdMapping
Long getId();
String getName();
}
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
UserDto a = entityViewManager.find(entityManager, UserDto.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Page<UserDto> findAll(Pageable pageable);
The best part is, it will only fetch the state that is actually necessary!

Hibernate Bytecode Instrumentation: Set fetched property values to their fields right away

I'm working on an enterprise application that uses Hibernate and EJB, and I'm utilizing Hibernate's Bytecode instrumentation to implement true lazy-loading of properties having bidirectional #OneToOne associations. I have a service method implemented using EJB, and as we all know, EJB uses RMI, which uses native Java serialization and deserialization to facilitate RPC invocations. The service method returns an entity with needed properties already fetched using JPQL, but since Hibernate doesn't set the fetched properties eagerly to their target fields, clients calling the service method end up receiving entities with properties having null values. Aside from calling the property getters manually before returning the entity, is there a way to tell Hibernate to set fetched property values automatically to their corresponding fields?
I'm using Hibernate 5.3.15 and JBoss EAP 7.2.8.
First of all, EJB doesn't necessarily use RMI, I guess what you mean is EJB remoting. There is no way that I know of to force field initialization except for initializing the fields through some means (access). One way to overcome this is to use DTOs that simply do not do any lazy initialization.
I think that this might be a bug in the serialization code of Hibernate for such bytecode enhanced proxies, so please create an issue in the issue tracker(https://hibernate.atlassian.net) with a test case(https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java) that reproduces the issue.
If you want to take the DTO approach, I think this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(User.class)
public interface UserDto {
#IdMapping
Long getId();
String getName();
UserDetailsDto getDetails();
#EntityView(UserDetails.class)
interface UserDetailsDto {
#IdMapping
Long getId();
String getFirstname();
}
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
UserDto a = entityViewManager.find(entityManager, UserDto.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Page<UserDto> findAll(Pageable pageable);
The best part is, it will only fetch the state that is actually necessary!

How to query only limited columns in Hibernate, and map them to a given POJO?

My project involves using GraphQL within a Spring Boot app. For demonstration purposes, here is my GraphQL schema:
type Company{
name: String,
parentOrganization: String,
flag:Int
}
I'm still learning Spring Boot and JPA, so I use spring-boot-starter-data-jpa for all the JPA, Hibernate, etc.
My problem is, when someone queries only for name and organization, Hibernate queries for all the columns and GraphQL picks the columns requested.
#Repository
#Transactional
public interface CompanyRepository extends JpaRepository<Company,Long> {
}
The above code doesn't really give me any flexibility in limiting the columns that are queried. I've tried using Hibernate's Criteria API as well, but whichever way I go, I get this error:
Unable to locate appropriate constructor on class [packagee.entity.company]. Expected arguments are: java.lang.String, java.lang.String [select new package.entity.Company(generatedAlias0.company, generatedAlias0.organization) from package.entity.Company as generatedAlias0]
Below is the code for my Criteria implementation:
public static List<Company> get(EntityManager em, List<String> fieldsAsked){
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Company> cq = cb.createQuery(Company.class);
Root<Company> root = cq.from(Company.class);
List<Selection<?>> selectionList = new LinkedList<Selection<?>>();
for(String name: fieldsAsked){
selectionList.add(root.get(name));
}
cq.multiselect(selectionList);
return em.createQuery(cq).getResultList();
}
How do I get limited columns from Hibernate? I've seen many answers online that ask to make appropriate constructor in the entity class, but that's not really possible for me because my entity parameters are mostly Strings and I cant make constructors for all the permutations possible (because I'm using GraphQL, the control of what to query really goes to the end user of my project).
What should I do? Thanks in advance!
What you want to do is not really possible with Hibernate directly, but you can checkout Blaze-Persistence Entity-Views which also has a GraphQL integration that supports exactly what you are looking for. See https://persistence.blazebit.com/documentation/1.6/entity-view/manual/en_US/#graphql-integration
Here is a sample project that shows how you can use this: https://github.com/Blazebit/blaze-persistence/tree/master/examples/spring-data-graphql
Solution 1:
You can create a new DTO class which will be returned by your query.
The DTO class:
public class CompanyDTO(){
//fields,constructor
}
And in the repository:
#Query(value = "SELECT new com.example.dto.companyDTO" +
"(c.name,c.parentOrganization)" +
" FROM Company c")
List<CompanyDTO>findCompanySelectedColumns(PageRequest pageable);
Solution 2(clean solution):
You can use interface. Do not implement the interface.
interface customCustomer{
String getName();
String getParentOrganization();
}
In repository:
List<CustomCustomer>findAllByNameAndParentOrganization();

Extend spring data's default syntax

In my current project almost every entity has a field recordStatus which can have 2 values:
A for Active
D for Deleted
In spring data one can normally use:
repository.findByLastName(lastName)
but with the current data model we have to remember about the active part in every repository call, eg.
repository.findByLastNameAndRecordStatus(lastName, A)
The question is: is there any way to extend spring data in such a way it would be able to recognize the following method:
repository.findActiveByLastName(lastName)
and append the
recordStatus = 'A'
automatically?
Spring Data JPA provides 2 additional options for you dealing with circumstances that their DSL can't handle by default.
The first solution is custom queries with an #Query annotation
#Query("select s from MyTable s where s.recordStatus like 'A%'")
public MyObect findActiveByLastName(String lastName);
The second solution is to add a completely custom method the "Old Fashion Way" You can create a new class setup like: MyRepositoryImpl The Impl is important as it is How spring knows to find your new method (Note: you can avoid this, but you will have to manually link things the docs can help you with that)
//Implementation
public class MyRepositoryImpl implements MyCustomMethodInterface {
#PersistenceContext
EntityManager em;
public Object myCustomJPAMethod() {
//TODO custom JPA work similar to this
String myQuery = "TODO";
return em.createQuery(myQuery).execute();
}
}
//Interface
public interface MyCustomMethodInterface {
public Object myCustomJPAMethod();
}
//For clarity update your JPA repository as well so people see your custom work
public interface MySuperEpicRepository extends JPARepository<Object, String>, MyCustomMethodInterface {
}
These are just some quick samples so feel free to go read their Spring Data JPA docs if you would like to get a bit more custom with it.
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/
Finally just a quick note. Technically this isn't a built in feature from Spring Data JPA, but you can also use Predicates. I will link you to a blog on this one since I am not overly familiar on this approach.
https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
You can use Spring Data's Specifications. Take a look at this article.
If you create a 'Base'-specification with the recordStatus filter, and deriving all other specifications form this one.
Of course, everybody in your team should use the specifactions api, and not the default spring data api.
I am not sure you can extend the syntax unless you override the base class (SimpleReactiveMongoRepository; this is for reactive mongo but you can find the class for your DB type), what I can suggest you is to extend the base methods and then make your method be aware of what condition you want to execute. If you check this post you get the idea that I did for the patch operation for all entities.
https://medium.com/#ghahremani/extending-default-spring-data-repository-methods-patch-example-a23c07c35bf9

Generic JPA repository for multiple entities

I have several entities and use Spring Data JPA repositories with specifications query my database. Therefore I created a generic class SpecBuilder to build my queries based on a query description (MyQueryDescriptor).
public class Specs {
public static <T extends MyEntityIFace> Specification<T> myfind(final MyQueryDescriptor qDesc) {
return new Specification<T>() {
#Override
public Predicate toPredicate(Root<T> root,
CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
try {
return SpecBuilder.mySpec(root, criteriaQuery, criteriaBuilder, qDesc);
} catch (Exception e) {
...handle error...
}
}
};
}
}
My repositories:
public interface Entity1DAO extends Repository<Entity1,Long>,
JpaSpecificationExecutor {
}
and
public interface Entity2DAO extends Repository<Entity2,Long>,
JpaSpecificationExecutor {
}
Now there are 3 things I am not quite sure about:
1)
Is this use of a generic SpecBuilder a clean design?
2)
Is there a way to avoid writing those repository interfaces for each entity? Let's say a generic repository?
3)
The MyQueryDescriptor class has a method to return an instance of an Entity, which will be queried.
What would be a clean way to obtain the according repository based on the entity class, avoiding a switch case? I was thinking about putting an annotation with the specific repository class to each entity but it feels a bit smelly.
Should I create a factory and inject a map like
Entity1.class => Entity1DAO
Entity2.class => Entity2DAO
?
You can use entity inheritance and use Spring Expression Language (SpEL) to make repository issue calls on right entities. Like in my last update here
Is this use of a generic SpecBuilder a clean design?
Depends what criteria you have for clean design. Will the same MyQueryDescriptor work for different entities? Surely they have different properties, so you need to ask yourself whether a given MyQueryDescriptor could be mistakenly used for an incompatible entity and ways in which you could prevent it. We cannot comment on that since we don't know how your SpecBuilder works.
Is there a way to avoid writing those repository interfaces for each entity? Let's say a > generic repository?
Nope. It's not much boilerplate either, though.
The MyQueryDescriptor class has a method to return an instance of
an Entity, which will be queried. What would be a clean way to obtain
the according repository based on the entity class, avoiding a switch
case?
I suppose you could use getBeanProvider at runtime, where you would define resolvableType as CrudRepository<MyEntityType, IdType>.
However, if I were you, I'd consider switching to using JPA Criteria API without the JpaSpecificationExecutor abstraction on top of it. That would probably prove to be more natural. The design of Spring repositories is centered around the idea of the repository organizing queries around the given specific entity, whereas your use case seems to go in exactly the opposite direction - to dynamically pick an entity and then find a repository to fit in, just to satisfy Spring's restrictions. You seem to be fighting the framework in that regard.

Categories

Resources