I am switching ORM framework from Hibernate to OpenJPA.
In Hibernate we could annotate a field with #ColumnTransformer like below.
#Column(name = "EMP_NAME", length = 4000)
#ColumnTransformer(
read = "pgp_pub_decrypt(emp_name::bytea,dearmor('"+key1+"'))",
write = "pgp_pub_encrypt(?, dearmor('"+key2+"'))"
)
private String empName;
How to do the same in OpenJPA
I am not sure of OpenJPA specific capabilities related to this, but the following two alternatives would work for all JPA providers:
Create an updatable view that does the necessary transformations and map the entity to the view instead of the table.
Move the transformations to middleware and apply them in entity lifecycle callbacks.
The other benefit of both solutions is that you keep the entities clean of custom native SQL.
Related
I'm trying to understand EclipseLink behaviour in case if I use native query. So I have Entity like this:
class Entity {
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="other_entity_id")
private OtherEntity otherEntity;
#Column(name = "name")
private String name;
//gets ... sets ...
}
and corresponding table looks like:
**ENTITY**
INTEGER ID;
VARCHAR NAME;
OTHER_ENTITY_ID;
And then I run native query
Query query = getEntityManager().runNativeQuery("select * from ENTITY", Entity.class);
query.getResultList()
Within Entity I have declared OtherEntity otherEntity which is annotated with FetchType.LAZY, however my query selects (*) - all of the columns, including OTHER_ENTITY_ID. The question is - if I run native query that fetches all columns, will fields annotated with FetchType.LAZY populated as if they were FetchType.EAGER or not? I've never worked with EclipseLink before and tyring to decide is it worth using it or not so I would really appreciate any help
Thanks, Cheers
My first advice is to turn on EclipseLink's SQL logging, and execute the equivalent JPQL to load what you are looking for and see the SQL EclipseLink generates to accomplish that to get an understanding of what is required to build objects in your native queries based on your current mappings.
Relationships generally loaded with a secondary query using the values read in from the foreign keys, so eager or lazy fetching is not affected by the native query to read in "Entity" - the query requires the other_entity_id value regardless of the fetch type. When required based on eager/lazy loading, EclipseLink will issue the query required by the mapping.
You can change this though by marking that the relationship is to use joining. In this case, EclipseLink will expect not only the Entity values to be in the query, but the referenced OtherEntity values as well.
I have an entity:
#Entity
public class VersionedDo {
#Version
#Column(name = "version")
private int version;
...
}
I want to update this entity without version increment in the some cases. Is there any way to do it without direct SQL update?
From Hibernate documentation :
Your application is forbidden from altering the version number set by Hibernate.
To artificially increase the version number, see the documentation for properties LockModeType.OPTIMISTIC_FORCE_INCREMENT or LockModeType.PESSIMISTIC_FORCE_INCREMENTcheck in the Hibernate Entity Manager reference documentation.
Therefore, using Hibernate, I guess you cannot force a version field to keep its original value when updating. You can only do the opposite.
You'll have to use a classic SQL query and don't forget to "refresh" your Hibernate object if needed.
I have a Class having two fields
#Column(name = "transactionDate", nullable = true)
private Date transactionDate;
#Column(name = "nextTransactionDate", nullable = true)
private Date nextTransactionDate
--
Both fields can be null. But if transactionDate is not null, then nextTransactionDate must not be null. How can I implement the above relationship between the fields using JPA? Any code snippet, link would be appreciated.
Note: I am using JPA not Hibernate.
You could validate this in your object model or application instead of through database constraints. You may also be able to define your own check constraint in the database through your own DDL script.
It's better to code the biz logic in DAO or service layer instead of defining it in ORM level. JPA and ORM tools is just designed to resolve persistence stuff not biz logic stuff.
Let's say we have an entity
#Entity
public class Person {
#Id int id;
#Basic String name;
#Basic String remark;
}
Let's say "remark" field is filled with big texts, but rarely used. So it would be good if when you run jpql: SELECT p FROM Person p, EclipseLink just executes sql select id, name from person
And than when you call person.getRemark(), it will get fetched with select remark from person where id = ?.
Is it possible with EclipseLink 2.1?
You can indeed define a fetch attribute in a Basic annotation and set it to LAZY. But let me quote what the specification says about it:
11.1.6 Basic Annotation
(...)
The EAGER strategy is a requirement
on the persistence provider runtime
that data must be eagerly fetched.
The LAZY strategy is a hint to the persistence provider runtime that
data should be fetched lazily when it
is first accessed. The implementation
is permitted to eagerly fetch data for
which the LAZY strategy hint has
been specified. In particular, lazy
fetching might only be available for
Basic mappings for which
property-based access is used.
In the particular case of EclipseLink, the behavior will depend on the context (Java EE vs Java SE) as explained in What You May Need to Know About EclipseLink JPA Lazy Loading.
In a Java EE environment (assuming the container implements the appropriate container contracts of the EJB 3.0 specification):
EclipseLink JPA performs lazy loading when the fetch attribute is set to javax.persistence.FetchType.LAZY.
In a Java SE environment:
By default, EclipseLink JPA ignores the
fetch attribute and default javax.persistence.FetchType.EAGER applies.
To configure EclipseLink JPA to perform lazy loading when the fetch attribute set to FetchType.LAZY, consider one of the following:
How to Configure Dynamic Weaving for JPA Entities Using the EclipseLink Agent
How to Configure Static Weaving for JPA Entities
Try add annotation #Basic(fetch = FetchType.LAZY)
#Entity
public class Person {
#Id int id;
#Basic String name;
#Basic(fetch = FetchType.LAZY) String remark;
}
We solved this problem (when using ActiveRecord and Hibernate) by putting the large string (usually a CLOB or BLOB) into it's own table with a FK to the main table (Person in this case.) Then it works like you want.
I am using the Hibernate Tools ant task to generate DDL from JPA annotated entities. With hibernate annotations you can name the foreign key using
#JoinColumn(name = "foo")
#org.hibernate.annotations.ForeignKey(name = "fk_foo")
Is there a pure JPA way of achiving the same?
No. JDO is the only persistence specification allowing definition of FK names, onUpdate/onDelete actions etc. JPA (even in JPA2) simply doesn't go there.
--Andy (DataNucleus)
Not in annotation. You can however set the columnDefinition and write the foreign key in there.