I am trying to test jpa queries in a separate projects entities by quickly kicking off a spring boot project to generate a platform to insert data into a H2 database, run queries against it, and validate the results of these queries.
Because the separate project has a large entity base, I'd like to selectively pick out the entities that I want to per test.
I've tried to use the #EntityScan annotation for this, but it seems designed to pull entire packages, even if you just specify a class.
This strikes me as something that there must be a solution for, but I have so far been unable to find it.
The thing is that when you set up a test class with a Spring context, that context exists for all the tests in that class, unless you use #DirtiesContext or some other trick to make it rebuild itself.
#EntityScan(basePackageClasses = MyEntity.class)
The code above doesn't tell Spring to use MyEntity, it tells it to start searching for entities in the package that MyEntity exists in. It also does so recursively, so if you have for instance:
com.example.entities.MyEntity
com.example.entities.subpackage.MyOtherEntity
It would pick up both MyEntity and MyOtherEntity. If, however, you wrote your EntityScan like this:
#EntityScan(basePackageClasses = MyOtherEntity.class)
Then MyEntity would not be found.
With that in mind, the only suggestion I have for you is perhaps to group your large number of entities into multiple smaller subpackages to make it easier to load, if loading all of them at once is indeed a showstopper for you.
So, I came up with a solution using Hibernate specific code. The Hibernate SessionFactoryBeans have an addAnnotatedClass method, so if you create a LocalSessionFactoryBean bean in your configuration file, you can just pass in the individual classes that you want. If you get a little creative, you can add the classes you want to test (I also have a DependencyGrapher that lets me know all the entity classes I need to pull in) as #TestPropertySource's in your test class and reference those values in the set up code.
It's actually pretty easy if you are using Hibernate, which, unfortunately, I am not able to do. I'm constrained to use EclipseLink, which just doesn't seem to offer this out of the box. I think I have a lead with Spring's PersistenceUnitPostProcessor though.
Related
the Topic already says one of the key roles regarding ORM
Don't run your own ORM Implementation
But, I have a situation here where I'm not sure how to get our Requirements implemented properly.
To give you a bit of background, currently we are using Spring Data JPA with Hibernate as JPA Implementation and all is fine so far.
But we have separate fields which we want to "manage" automatically, a bit similar to Auditing Annotations from Hibernate (#CreatedBy, #ModifiedBy, ...).
In our case this is e.g. a specific "instance" the entity belongs to.
Our Application is rather a Framework than an App, so other Developers frequently add Entities and we want to keep it simple and intuitive.
But, we do not only want to set it automatically on storage but also add it as condition for most "simple and frequent" queries (see my related question here Inject further query conditions / inject automatic entity field values when using Spring Data JPA Repositories).
Thus, I thought about building a simple Layer on top of the EntityManager and its Criteria API to support at least simple Queries like
findById(xx)
findByStringAttribute(String attribute, String value)
findByIntegerAttribute(int attribute, String value)
...
I'm not sure if this is too broad of a question but, what are your thoughts on that? Is this a reasonable idea or should I skip that idea?
My application has about 50 entities that are displayed in grid format in the UI. All 50 entities have CRUD operations. Most of the operations have the standard flow
ie. for get, read entities from repository, convert to DTO and return a list of DTO's.
for create/update/delete - get DTO's - convert to entities, use repository to create/update/delete on DB, return updated DTOs
Mind you that for SOME entities, there are also some entity specific operations that have to be done.
Currently, we have a get/create/update/delete method for all our entities like
getProducts
createProducts
updateProducts
getCustomers
createCustomers
updateCustomers
in each of these methods, we use the Product/Customer repository to perform the CRUD operation AFTER conversion from entity -> dto and vice versa.
I feel there is a lot of code repetition and there must be a way by which we can remove so many of these methods.
Can i use some pattern (COMMAND PATTERN) to get away with code repetition?
Have a look at the Spring Data JPA or here project. It does away with boilerplate code for DAO.
I believe it basically uses AOP to interpret calls like
findByNameandpassword (String name,String passwd)
to do a query based upon the parameters passed in selecting the fields in the method name (only an interface).
Being a spring project it has very minimal requirements for spring libraries.
Basically, you have 2 ways to do this.
First way: Code generation
Write a class that can generate the code given a database schema.
Note that this you will create basic classes for each entity.
If you have custom code (code specific to certain entities) you can put that in subclasses so that it doesn't get overwritten when you regenerate the basic classes.
Object instatiation should be via Factory methods so that the correct subclass is used.
Make sure you add comments in the generated code that clearly states that the code is generated automatically (so that people don't start editing them directly).
Second way: Reflection
This solution, while being more elegant, is also more complex.
Instead of generating one basic class for each entity you have one basic class that can handle any entity. The class would be using reflection to access the DTO:s.
If you have custom code (code specific to certain entities) you can put that in other classes. These other classes would be injected into the generic class.
Using reflection would require a strict naming policy on your DTO:s.
Conclusion
I have been in a project using the first method in a migration project to generate DTO classes for the service interface between the new application server (running java) and the fat clients and it worked quite well. We had more than 100 generated DTO classes. I am aware that what you are attempting is slighty different. Editing database records is a generic problem (all projects need it) but there aren't (m)any frameworks for it.
I have been thinking about creating a generic tool or framework for it but I have never gotten around to it.
I am somewhat new to using JPA -- I'll put that out there right off the bat. I'm getting more familiar with it, but there are big holes in my knowledge right now.
I am working on an application that uses JPA, and deletes entities using the EntityManager.remove(Object entity) function. However, the application also links into a third-party application, and I would like to add logic that gets executed whenever a certain type of Entity is removed from the persistence layer.
My question is this. Is there a way to add logic to the EntityManager.remove(Object entity) function on a Entity class level, such that every time that type of entity is deleted the extra logic is executed?
Thanks much.
Entity class may have methods annotated with #PreRemove or #PostRemove.
If you are using Eclipselink, it has a much more fine grained native event system via the DescriptorEventListener interface.
I want to achieve basic CRUD operations available of the db schema I already have for a JAVA program. To put it in another way, I have a DB schema I use with PHP and I just need them to be entities available in a JAVA application. I discovered I can use Netbeans and sucessfully created Entities from DB!
(Entities look like this: http://pastebin.com/f601b9218)
However when I try to create New > JPA controllers from entity classes in Netbeans I got empty JPA controller classes like:
package javaapplication3;
public class CustomerJpaController {
}
It is empty :) I was expecting CRUD functions inside the generated JPA controller classes as I read from examples and tutorials.
What could be the reason of empty JPA controller classes? Is there any other easy way for me to "just" match DB tables with JAVA classes for basic CRUD operation. (I wish there could be easy way to achieve active record pattern)
Thanks in advance.
Usually, I never like to go too much with the wizard thing. But it seems like it should generate the basic CRUD operations, though. I don't know exactly which tutorial you followed. Right now, I am looking at this. After reading this I am getting the same impression, by the way. But may be it just generates the empty classes, and nothing else. I am not sure never tried to do that.
However, coding it yourself would be quite simple, I believe. Especially when you already got the NamedQueries defined for your entities.
Currently we are testing out entity classes and "worker" classes by writing java servlets for each entity and doing Insert,update,delete,find... for each entity to ensure that it works. The worker classes are simply implementations of an interface that persists the entity to the database using JDBC, they do the DB work for the entity.
What I'm wondering is, what is the best way to test entity classes in Java?
I'm looking for an automated approach rather than writing, basically, a mock application that calls all of the functions that I'm trying to test for each new entity that is created.
You should be able to set-up and use entity and "worker" (as you put it) classes independently or servlets and a Web container.
With pure JDBC and JUnit, you would typically do the following:
Open a JDBC connection in TestCase constructor.
Begin a transaction on setUp().
Rollback a transaction on tearDown().
Use the actual entity instances in the particular testXxx() methods.
In this approach, you would be having one, possibly local, database instance per developer. For something more advanced, consider DbUnit.
One option would be to use reflection to find the different pieces of the entities (i.e. different fields) and then have the method call save, update, delete, etc using those different entities. Then, when you added a new entity, if your setup is done using xml or something similar, the test will just pick them up.
I am speaking from a Hibernate user perspective, so this may not be entirely applicable to your situation, but it has worked well for me in the past.