Unable to access MetaModel entity attributes - jpa

I have tried to access the MetaModel entity attributes/variables using the code below:
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Metamodel m = entityManager.getMetamodel();
EntityType<User> User_ = m.entity(User.class);
Root<User> userRoot = criteria.from(User.class);
criteria.where(builder.equal(userRoot.get(User_.email)), user.getEmail());
but email cannot be resolved or is not a field.
Is it mandatory to create StaticMetaModel class for User class. i.e., "User_" ???
If YES, please see the link http://docs.oracle.com/javaee/6/tutorial/doc/gkjbq.html
here, you can find the below code:
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> Pet_ = m.entity(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.where(cb.equal(pet.get(Pet_.name), "Fido"));
Please help me here.

That Oracle documentation you refer to is utterly wrong. The STATIC metamodel is generated by an annotation processor. It is not obtained via the JPA Metamodel class.
The STATIC (canonical) metamodel class with "_" is not an EntityType object.
See the JPA spec section 6.2.1.1 and documentation such as this one.

Related

Does Hibernate Search work on fields annotated with JPA Converter

I am storing few fields as JSON using JPA Converter annotation, does Hibernate Search provide support for indexing/searching these fields?
Hibernate Search doesn't see the "converted" side of your properties (in this case, the JSON).
If you have this:
#Convert(class = MyJsonConverter.class)
private MyObject myObject;
Then all Hibernate Search will see is an instance of MyObject. You can use #Field or #IndexedEmbedded as you would with any other property.
#Column(name="address")
#Convert(class = AddressConverter.class)
private Address fieldAddress;
If you convert your object to String for example. You can use something like with CriteriaBuilder
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<SomeObject> query = cb.createQuery(SomeObject.class);
Root<SomeObject> from = query.from(SomeObject.class);
query.select(from).where(cb.equal(root.get("fieldAddress").as(String.class), "address in string"));
If you using Spring Data JPA, your way is using #Query
#Query(select * from SOME_TABLE where ADDRESS = ?1, nativeQuery = true)
List<SomeObject> findAllByMyObj(String address);
P.S. If you using Metamodel and you should to save consistent of your Query(check the documentations Hibernate JPA static metamodel generator), it would looks like
query.select(from).where(cb.equal(root.get(SomeObject_.fieldAddress).as(String.class), "address in string"));

A strange phenomenon when use dozer in jpa project,why Mapping annotation in lazy load object can't work?

I met a very strange phenomenon when using dozer in jpa project.
I have a UserSupplier object and a Supplier object.
UserSupplier:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "supplier_id", nullable = false)
private Supplier supplier;
In my code I first query a UserSupplier List, then convert it to SupplierList.
List<Supplier> supplierList = new ArrayList<>(usList.size());
usList.forEach(us -> supplierList.add(us.getSupplier()));
Then I convert SupplierList to SupplierView List and return it to Caller.
BeanMapper.mapList(supplierList, SupplierView.class);
My dozer configure in these objects like below
Supplier:
#Id
#GeneratedValue
#Mapping("supplierId")
private int id;
SupplierView:
private int supplierId;
Very funny, supplierId in SupplierView always 0(default int value),but other fileds can convert successfully, only id field fail. I don't why is this, why only id field can't convert to supplierId, but other fields could?
For above problem, there are below solutions
1. Change field name (supplierId to id):
Supplier:
// #Mapping("supplierId")
private int id;
SupplierView:
private int id;
but Caller(front-end) have to change code.
2. Change fetchType to eager:
UserSupplier:
#ManyToOne
private Supplier supplier;
After reading dozer documentation, I find some thing. After trying it, I got another solution.
That is add a dozer.properties into classpath, content inside is
org.dozer.util.DozerProxyResolver=org.dozer.util.HibernateProxyResolver
More detail please see
http://dozer.sourceforge.net/documentation/proxyhandling.html
This is probably because JPA uses proxy objects for lazy loading of single entity reference. Proxy object is effectively a subclass of your entity class. I guess that dozer can find #Mapping annotation only on fields declared in the class of given object, and not on fields defined in parent classes. Dozer project states that annotation mapping is experimental. Therefore it is possible that it does not cover mapping class hierarchies well.
I suggest to try configure mapping of supplierId by other means (XML, dozer mapping API) and see if it works. If all fails, you could write a custom MapperAware converter between Supplier and SupplierView. You would map source object to target object using supplied mapper, and finilize it by copying value of id to supplierId.

EclipseLink JPA Dynamic model and Criteria Query

i like to create a (crtieria-) query against a dynamic model but i always get the exception
No [EntityType] was found for the key class [demo.DynamicResult] in the Metamodel
at the last line
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Tuple> query = criteriaBuilder.createTupleQuery();
DynamicHelper helper = new DynamicHelper(JpaHelper.getServerSession(emf));
Class<? extends DynamicEntity> rootclass = helper.getType("demo.DynamicResult").getJavaClass();
query.from(rootclass);
The DynamicResult gets generated with following code
ServerSession serverSession = JpaHelper.getEntityManager(entityManager).getServerSession();
DynamicClassLoader dcl = DynamicClassLoader.lookup(serverSession);
JPADynamicHelper jpaDynamicHelper = new JPADynamicHelper(entityManager);
Class<?> dynamicResult = dcl.createDynamicClass("demo.DynamicResult");
JPADynamicTypeBuilder dynamicResultBuilder = new JPADynamicTypeBuilder(dynamicResult, null, "DynamicResult");
dynamicResultBuilder.addDirectMapping("id", String.class, "id");
//Some more addDirectMappings ....
dynamicResultBuilder.setPrimaryKeyFields("id");
type = dynamicResultBuilder.getType();
jpaDynamicHelper.addTypes(false, false, type);
What did I missed ?
Is this kind of query possible at all ?
Regards
You may be hitting https://bugs.eclipse.org/bugs/show_bug.cgi?id=429760 bug. There was a problem with copying newly created dynamic entity metadata into current session.
Check this bug and attached diffs. jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/dynamic/simple/SimpleQueryTestSuite.java test suite contains test which does similar thing - creates dynamic entity and runs JPQL query against it within the same transaction (UnitOfWork).
I would try latest 2.7.0 or 2.6.1 (do not use .WAS) build from https://www.eclipse.org/eclipselink/downloads/nightly.php to see if it works fine for you.

Accessing Roo Identifier

I have this entity class having more than one primary key (#Id) which resulted me to use #RooJpaActiveRecord(identifierType = '<IdentifierClass.class>') and #RooIdentifier(dbManaged=true). Yet I am having a problem on accessing Identifier.class from the entity class itself.
My questions is how can I access Identifier in the entity class without, at most, removing the #RooJpaActiveRecord(identifierType = '<Identifier.class>') code.
Roo will generate a property id on your entity. This property is declared on MyEntity_Roo_Jpa_Entity.aj file (this includes a getter/setter). So, you simple use:
MyEntity myEntity = new MyEntity();
myEntity.setId(new Identifier());
myEntity.getId().setPk1(value1);
// ....
// ....
myEntity.getId().setPkn(valuen);

How to get a reference to superior object from Entity object

How to get a reference to superior ObjectContext from EntityObject class?
Have a look at the following link:
http://blogs.msdn.com/alexj/archive/2009/06/08/tip-24-how-to-get-the-objectcontext-from-an-entity.aspx
It is like the way that Nix mentioned as an extenxtion to the entity object.
Only way you can do it is via a hack using relationships, and an entity that is not detached. See below.
YourEntity someEntity = null;
RelationshipManager relationshipManager = ((IEntityWithRelationships)someEntity ).RelationshipManager;
IRelatedEnd relatedEnd = relationshipManager.GetAllRelatedEnds().FirstOrDefault();
ObjectQuery getContext = relatedEnd.CreateSourceQuery() as ObjectQuery;
YoutObjectContext c1 = (YourObjectContext)getContext .Context;
Good luck with it. If you use the code above i recommend protecting it with null checks.