Is is possible to create a custom jpa annotation in java - 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.

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!

Is it possible to map Spring Data Couchbase with external document (from dependency)?

I need to retrieve data from legacy Couchbase bucket without a specific schema. It can be mapped as com.couchbase.client.java.document.StringDocument from the Couchbase Java client. I can do this directly using Java client:
bucket.get(key, StringDocument.class)
But how can I map this StringDocument using org.springframework.data.repository.CrudRepository?
I can't create such interface interface UserRepository extends CrudRepository<StringDocument, String> because Spring Data Couchbase requires #Document and #Id annotations.
All entities should be annotated with the #Document annotation. Also, every field in the entity should be annotated with the #Field annotation. While this is - strictly speaking - optional, it helps to reduce edge cases and clearly shows the intent and design of the entity.
There is also a special #Id annotation which needs to be always in place. Best practice is to also name the property id.
Should I directly use Bucket, create my own similar entity, or there is another solution?
I use following version of spring-boot-starter-data-couchbase: 1.5.9.RELEASE.
If its just a StringDocument (and it wasn't even saved by spring-data-couchbase to begin with.. which injects the _class attribute for deserialization purposes) then I'd just use the bucket to retrieve it.
Keep in mind if your repository (I'm talking about any other repository you have defined that is mapped to the same bucket the StringDocument is in) is defined as CouchbaseRepository you will be able to access the bucket itself from the repository methods like so repository.getCouchbaseOperations().getCouchbaseBucket(). Or maybe you can try the following repository.getCouchbaseOperations().findById("id", StringDocument.class).

Annotation based hibernate mapping for external classes

Is it possible to provide annotation based hibernate mapping informations for external classes?
I have a model class (for example Credit) in an external package (without any dependencies to hibernate) which I can't / wan't edit and now I wan´t to define mapping informations for this class.
It's no problem to define these mapping informations in a xml file but I am looking for a possibility to define these informations via annotations.
I can extend the model class but then the child class is mapped but i wan't to map the superclass.

JPA using variable Schema name in annotations

I'm using the Java Persistence API to describe tables from my database that i will manipulate in my code.
However, the schema used is not be the same depending on where my project will be installed. So, when I use the annotations, I would like that the SCHEMA field was a variable, but I can't make it:
#Entity
#Table(name = "TABLE_NAME", schema = schemaVariable, catalog = "")
How can I achieve that?
Is it possible with the persistence.xml file?
No, this is not possible. You can only use compile-time constants (which are all primitives and String) in annotations.
You can use final variables:
public class DatabaseMetadata {
public static final SCHEMA = "MySchema";
}
and then use it in annotation:
#Table(name = "TABLE_NAME", schema = DatabaseMetadata.SCHEMA, catalog = "")
but I think it's not what you wanted.
PS. On the other hand, there can be find examples of using i.e. Spring EL in annotations (see #Value annotation), but this requires custom annotation processor. AFAIK none of JPA providers gives you such ablility.
Putting schema information (like table, column, schema names) in java classes is a bad idea any time IMHO (forcing recompile if you want to deploy elsewhere). You could put that info in orm.xml and just deploy a different orm.xml dependent on your deployment requirement.
As for persistence.xml you would be dependent on your JPA provider having a persistence property that defined the default schema/catalog. I know DataNucleus JPA (what I use) has this, but no idea for Hibernate
If you know that you would be using different schemas, I'd suggest to use 2 mapping files and define
<entity-mappings>
<persistence-unit-metadata>
<persistence-unit-defaults>
<schema>HR</schema>
</persistence-unit-defaults>
</persistence-unit-metadata>
...
</entity-mappings>
In this way you will be able to easily change schemas, without any changes in the application code.

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

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

Categories

Resources