Answers like https://stackoverflow.com/a/12828955/3395716 and https://stackoverflow.com/a/32184186/3395716 and many others mention of some enitityManager.getReference() method, which can be used to avoid making unnecessary select queries to the database.
I am having similar issue in spring boot app, when trying to save an object to the database, using CRUDRepository. My class looks like,
class StudentSubject {
String studentId;
#ManyToOne
private Subject subject;
#ManyToOne
private Student student;
}
I have to unnecessarily make find() calls to get the student and subject objects from the database, only to pass them to StudentSubjectRepository to save() them. But I already have the primary keys of both subject and student. So I would like to use them instead, and entityManager looks like what I need.
But I have no idea where this entityManager comes from, or if there is any equivalent to it in Spring Boot.
If you use JpaRepository interface for your repository instead of CRUDRepository, you will gain access to getOne(id) method which is the equivalent of the entityManager.getReference.
It's injected normally, Spring Boot has nothing to do with it (Spring Boot is just Spring albeit with some configuration differences).
Just add
#PersistenceContext
private EntityManager em;
to your class and you can access the raw EntityManager object and all that it offers. There's nothing wrong with using it, you can't get everything done with repositories.
Related
I have the following question. From what I understand the #Transactional annotation is supposed to keep the session alive, thus enabling to lazy fetch child entities without the need to performe a specific joining query.
I have the following scenario where I do not understand why I'm still getting a LazyInitializationException.
My app runs a resolver in order to provide the various controller services with a resolved object so that it can be used directly.
Said resolver intercepts a header from the request and using it's value attempts to query the db in order to fetch the object. Now the object in question is quite simple is it's doings albeit it has a list of two sub-entities.
In order to perform the resolving action I'm using an extra service where I basically wrap some JpaRepository methods. The complete is below:
#Service
public class AppClientServiceImpl implements AppClientService {
private static final Logger LOGGER = LoggerFactory.getLogger(AppClientServiceImpl.class.getCanonicalName());
private final AppClientRepository repository;
#Autowired
public AppClientServiceImpl(AppClientRepository repository) {
this.repository = repository;
}
#Override
#Transactional(readOnly = true)
public AppClient getByAppClientId(final String appClientId) {
LOGGER.debug("Attempting to retrieve appClient with id:: {}", appClientId);
return repository.findByAppClientId(appClientId);
}
#Override
#Transactional
public void saveAndFlush(final AppClient appClient) {
LOGGER.debug("Attempting to save/update appClient:: {}", appClient);
repository.saveAndFlush(appClient);
}
}
As you can see both methods are annotated as #Transactional meaning that the should keep the session alive in the context of that said method.
Now, my main questions are the following:
1) Using the debugger I'm seeing even on that level getByAppClientId the list containing on the sub-entities which is lazy loaded has been resolved just fine.
2) On the resolver itself, where the object has been received from the delegating method, the list fails to be evaluated due to a LazyInitializationException.
3) Finally on the final controller service method which is also marked as #Transactional, the same as above occurs meaning that this eventually fails to it's job (since it's performing a get of the list that has failed to initialize.
Based on all the above, I would like to know what is the best approach in handling this. For once I do not want to use an Eager fetching type and I would also like to avoid using fetch queries. Also marking my resolver as #Transactional thus keeping the session open there as well is also out of the question.
I though that since the #Transactional would keep the session open, thus enabling the final service method to obtain the list of sub-entities. This seems not to be the case.
Based on all the above it seems that I need a way for the final service method that gets call (which needs the list on hand) to fetch it somehow.
What would the best approach to handle this? I've read quite a few posts here, but I cannot make out which is the most accepted methods as of Spring boot 2.0 and hibernate 5.
Update:
Seems that annotating the sub-entitie with the following:
#Fetch(FetchMode.SELECT)
#LazyCollection(LazyCollectionOption.TRUE)
Resolves the problem but I still don't know whether this is the best approach.
You initialize the collection by debugging. The debugger usually represents collections in a special way by using the collection methods which trigger the initialization, so that might be the reason why it seems to work fine during debugging. I suppose the resolver runs outside of the scope of the getByAppClientId? At that point the session is closed which is why you see the exception.
I created Blaze-Persistence Entity Views for exactly that use case. You essentially define DTOs for JPA entities as interfaces and apply them on a query. It supports mapping nested DTOs, collection etc., essentially everything you'd expect and on top of that, it will improve your query performance as it will generate queries fetching just the data that you actually require for the DTOs.
The entity views for your example could look like this
#EntityView(AppClient.class)
interface AppClientDto {
String getName();
}
Querying could look like this
List<AppClientDto> dtos = entityViewManager.applySetting(
EntityViewSetting.create(AppClientDto.class),
criteriaBuilderFactory.create(em, AppClient.class)
).getResultList();
I've implemented soft delete in my spring boot application. Which looks something like:
Program.java
public class Program{
//other attributes
private boolean deletedFlag;
//getter setters
}
And in repository of program entity, I'm firing following query to only return the entities, which has deleted flag false.
public interface ProgramRepository{
//other methods
Program findByDeletedFlagFalse();
}
So this implementation works perfectly fine. But the problem is, I've an another entity (named 'Major'), in which I've injected list of programs. So major entity looks like:
public class Major{
//other fields
List<Program> programs;
//getter setters
}
Now, when I delete program entities, it still appears in the major, even if they are deleted. So basically my response looks like:
"major":{
//other fields
"program": [{
//other fields
"deletedFlag": true
}]
}
But the expected behavior should be like if we delete child entity, parent should not list it. So what am I missing here?
Is there any alternative of implementing soft delete in spring boot? I've already seen this: Hibernate Soft Delete using update Cascade, But it seems like the answer using hibernate instead of Spring data JPA.
I've already seen this: Handling soft-deletes with Spring JPA, but it is more aligned to hibernet solution instead of spring data JPA.
I have a static method in the entity
#Transactional
public static void updateState() {
entityManager().createNativeQuery("UPDATE TABLEA SET hide = 1 WHERE id= 1").executeUpdate();
}
But when I call the method, I catch a exception say the update statement need a transaction.
Am I using the #Transactional in the wrong way?
It seems like you are trying to make your Entity a fat domain model (as opposed to thin models that are most common in the Java EE world) following the Active Record pattern.
What you are trying to do will not work as is in Spring.
If you refactor your method to not be static (first problem) then one way to get #Transactional working on a JPA entity is to use the #Configurable annotation from Spring (making it managed by Spring - therefore fixing the second problem), along with load time weaving and a Java agent. See this and this for more details.
Maybe you should try with the annotation:
#Transactional(readOnly=false)
I'm implementing several DAO classes for a web project and for some reasons I have to use JDBC.
Now I'd like to return an entity like this:
public class Customer{
// instead of int userId
private User user;
// instead of int activityId
private Activity act;
// ...
}
Using JPA user and activity would be loaded easily (and automatically specifying relations between entities).
But how, using JDBC? Is there a common way to achieve this? Should I load everiting in my CustomerDAO? IS it possible to implement lazy initialization for referenced entities?
My first idea was to implement in my UserDAO:
public void initUser(Customer customer);
and in my ActivityDAO:
public void initActivity(Customer customer);
to initialize variables in customer.
Active Record route
You could do this with AspectJ ITDs and essentially make your entities into Active Record like objects.
Basically you make an Aspect that advises class that implement an interface called "HasUser" and "HasActivity". Your interfaces HasUser and HasActivity will just define getters.
You will then make Aspects that will weave in the actual implementation of getUser() and getActivity().
Your aspects will do the actual JDBC work. Although the learning curve on AspectJ is initially steep it will make your code far more elegant.
You can take a look at one of my answers on AspectJ ITD stackoverflow post.
You should also check out springs #Configurable which will autowire in your dependencies (such as your datasource or jdbc template) into non managed spring bean.
Of course the best example of to see this in action is Spring Roo. Just look at the AspectJ files it generates to get an idea (granted that roo uses JPA) of how you would use #Configurable (make sure to use the activerecord annotation).
DAO Route
If you really want to go the DAO route than you need to this:
public class Customer{
// instead of int userId
private Integer userId;
// instead of int activityId
private Integer activityId;
}
Because in the DAO pattern your entity objects are not supposed to have behavior. Your Services and/or DAO's will have to make transfer objects or which you could attach the lazy loading.
I'm not sure if there is any automated approach about this. Without ORM I usually define getters as singletons where my reference types are initialized to null by default, i.e. my fetching function would load primitives + Strings and will leave them as null. Once I need getUser(), my getter would see if this is null and if so, it would issue another select statement based on the ID of the customer.
I'm trying to convert a legacy application to hibernate.
I have an entity that has a field, which should be instantiated to object instance based on a fully qualified name string in a database.
Consider the example below - if I have somePackageName.FirstClass in a database the someObject field should be an instance of FirstClass.
I guess I could use property access and persist / retrieve a string but that doesn't look very elegant to me.
I cannot use #PostLoad etc. - I'm using pure hibernate with spring (not JPA) - these annotations get ignored.
I know for example in MyBatis one can register a custom handler for field. Would anything similar be available in Hibernate?
I'm new to hibernate so I'm not really sure what the options are.
#Entity
class SomePersistentClass{
private SomeInterface someObject;
}
class FirstClass implements SomeInterface{
}
class SecondClass implements SomeInterface{
}
You can use JPA features such as #PostLoad, etc callbacks simply by enabling the proper Hibernate event listeners. Check the Hibernate EntityManager guide for details.
But this one is even easier. This is the role of a Type in Hibernate. First, you'll have to write an implementation of org.hibernate.type.Type or org.hibernate.usertype.UserType and specify that in #Type( type=... ) that handles the conversions (lots of web resources about writing custom Hibernate types). Then annotate your 'someObject' attribute with #Type( type="your.custom.TypeImpl" )