How to instantiate a class from string FQN in database in hibernate? - java

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" )

Related

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!

#Transient not working in hibernate

I am using hibernate 4.1.9.
My code is
#Transient
private String ldapIdTemp;
package is
import javax.persistence.Transient;
Still in hibernate query, it is not working and putting the attribute in the query.
part of query snippet (assetasset0_.ldapIdTemp as ldapIdTemp16_0_, )
I am not sure what I am doing wrong.
Can you try creating setter and getter for the field and annotate the get method with #Transient, as follows:
private String ldapIdTemp;
#Transient
public String getLdapIdTemp() {
return ldapIdTemp;
}
public void setLdapIdTemp(String ldapIdTemp) {
this.ldapIdTemp = ldapIdTemp;
}
Much depends on how you "integrated" this field in your Entity or class hierarchy. Moreover, field vs. property-access could cause an issue for your setting. See this post for a detailed explanation.
In your case, I could imagine that you either:
mixed field and property-access in your entity inheritance strategy
use XML-based configuration for Hibernate in your application.
In both cases the JPA 2.0/2.1 specification clearly states in Section 2.3.1:
It is an error if a default access type cannot be determined and an access type is not explicitly specified
by means of annotations or the XML descriptor. The behavior of applications that mix the placement of
annotations on fields and properties within an entity hierarchy without explicitly specifying the
Access annotation is undefined.
Please check that your persistent Entity classes have either field OR property-based annotations.
Check the #Transient annotation fully qualified name.
It can be from either,
org.springframework.data.annotation.Transient or javax.persistence.Transient.
Try to use javax.persistence.Transient.

Is it possible to map a normal Java bean for Hibernate in a separate class / file?

I have a normal model class
public class Person {
private int id;
private String name;
...
}
It's a model class and doesn't have any JPA / Hibernate annotations used.
Is it possible to somehow tell Hibernate to make this class persistent?
I want to use Person in queries, criteria etc, but don't want to introduce annotations to that class (it is defined in a model JAR with no JPA dependency, and I have the DB code in a different JAR);
Hibernate supports XML mappings to map a class to a database, as well as annotations.

Initialize JPA-like entities with JDBC

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.

Is is possible to create a custom jpa annotation in java

Jpa one of the big successfull module of jpa and so are its annotation features .I have weird requirement in which i need to create jpa annotation ,one that jpa can process
ex. We have in jpa a table annotation that create a table for this java pojo class.
i need to make another annotation that behaves exactly as what table annotation does + some of my custom reqirements;
what is mean
if i create a customAnnotation like #Anil that is suppose to work same as #Table Annotation does
than
#Anil
public class Anp
{
}
than this should create a table in the database is that possible or not .if it is give me some way to do this
thanks
JPA does not process just any annotation. The JPA implementation processes the annotations that it supports and these are typically just the javax.persistence annotations, and optionally its own extensions. Your JPA provider may allow you to define your own, but this is not going to be very common - look at the docs for your JPA provider if they allow a user to define annotations.
For example, the JPA provider I have used (DataNucleus JPA) allows the user to provide annotations for the class or for the field/property.

Categories

Resources