Abstract Entity Persister Method get Property Values Illegal Argument Exception in Class - java

I'm getting error on DAO class Object[] property value variable,method of getPropertyValues(Object object ,EntityMode.Pojo); Is it correct way I am accessing property values based on property names ?please let me know where I have made mistaken ?
Using hibertnate-core 3.6.1 Final.jar.
My full Stack Trace :
[ERROR] IllegalArgumentException in class: com.zpmc.ecs.domain.ExportReport, getter method of property: description - (BasicPropertyAccessor.java:194)
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.zpmc.ecs.domain.ExportReport.description
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:198)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValues(AbstractEntityTuplizer.java:482)
at org.hibernate.tuple.entity.PojoEntityTuplizer.getPropertyValues(PojoEntityTuplizer.java:241)
at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValues(AbstractEntityPersister.java:3857)
at com.zpmc.ecs.autoexportbean.AutoExportListenerService.getAllTables(AutoExportListenerService.java:327)
at com.zpmc.ecs.autoexportbean.AutoExportListenerService.buildReport(AutoExportListenerService.java:154)
at com.zpmc.ecs.autoexportbean.AutoExportListenerService.getAutoExportExcel(AutoExportListenerService.java:130)
at com.zpmc.ecs.autoexportbean.MyTask.run(AutoExportListenerBean.java:137)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:172)
... 9 more
Pojo Class :
#Entity
#Table(name ="T_KPI_AUTO_EXPORT_CONFIG")
public class ExportReport implements Serializable {
private String description;
#Column(name ="Description", nullable = false)
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
DAO Class Method :
public List <String> getAllTables() throws SQLException {
Map<String, ClassMetadata> classMetaDataMap = hibernateTemplate.getSessionFactory().getAllClassMetadata();
for(Map.Entry<String, ClassMetadata> metaDataMap : classMetaDataMap.entrySet()) {
ClassMetadata classMetadata = metaDataMap.getValue();
AbstractEntityPersister abstractEntityPersister = (AbstractEntityPersister) classMetadata;
tableName = abstractEntityPersister.getTableName();
String[] propertyNames = abstractEntityPersister.getPropertyNames();
for(int i=0;i<propertyNames.length;i++){
Object[] propertyvalue =abstractEntityPersister.getPropertyValues(ExportReport.class,EntityMode.POJO);
System.out.println(propertyType+"Columns: " + propertyNames+"ddddd"+propertyvalue);
System.out.println(propertyNames[i]);
System.out.println(propertyvalue[i]);
}
}
}

Related

Is there another way to instantiate a concrete instance of an abstract class inside a list during spring databind?

Given the following classes:
#Data #MappedSuperclass #Accessors(chain = true)
public abstract class EntidadeDeDominio {
public EntidadeDeDominio() {
type = getClass().getSimpleName();
}
#Id #GeneratedValue(strategy = GenerationType.AUTO) #TableGenerator(name="entity_gen", initialValue = 1)
private Long id = 0L;
private String type;
}
#Data #Entity
public abstract class EntidadeAuditavel extends EntidadeDeDominio {
#CreatedBy
private String criadoPor;
#CreatedDate
private Date criadoEm;
#LastModifiedBy
private String modificadoPor;
#LastModifiedDate #Temporal(TemporalType.TIMESTAMP) #JsonDeserialize(using = CustomDateDeserializer.class) #JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss'T'")
private Date modificadoEm;
}
#Data #Entity #Accessors(chain = true)
public class OrdemDeVenda extends EntidadeAuditavel {
private long numero;
#OneToMany(orphanRemoval=true, mappedBy="ordemDeVenda")
private List<ItemVenda> itemVenda;
}
#Data #Entity
public abstract class ItemVenda extends EntidadeAuditavel {
#ManyToOne
private OrdemDeVenda ordemDeVenda;
#OneToMany
private List<DestinoItemVenda> destinoItemVenda;
}
#Data #Entity #Accessors(chain = true)
public class Equipamento extends ItemVenda {
private long numero;
private String modelo;
#OneToMany(orphanRemoval = true, mappedBy="equipamento")
private List<Modulo> modulo;
public String toString() {
return String.valueOf(numero);
}
}
#Data #Entity
public class ProdutoGenerico extends ItemVenda {
private String descricao;
#OneToMany(orphanRemoval = true)
private List<Imposto> imposto;
private double preco_unitario;
public String toString() {
return descricao;
}
}
By being it's child, they all inherit a type attribute from the class EntidadeDeDominio and this attribute is also sent by the form by using a hidden field.
And, to resume a little, some info about the form:
Parameters received from the form when the object is an ProdutoGenerico
[id, type, numero, itemVenda[0].type, itemVenda[0].descricao]
Some of the parameters received from the form when the object is an Equipamento
[id, type, numero, itemVenda[0].type, itemVenda[0].modelo]
And the problem:
Spring, during DataBind (to a #ModelAttribute OrdemDeVenda object), fails to fill the List<ItemVenda> itemVenda because because ItemVenda is an abstract class.
And the current workaround:
After several seriously painful headaches and with the help of another post (How to bind a subclass of an abstract class in a Spring-MVC method?) I managed to get the following code to work (hardcoding the routine to use the 'type' attribute to instantiate the correct class and populate the list).
#InitBinder
public void registerConversionServices(WebDataBinder binder, HttpServletRequest request) {
Object nonCasted = binder.getTarget();
if(nonCasted == null || !(nonCasted instanceof OrdemDeVenda)) {
return;
}
OrdemDeVenda ov = (OrdemDeVenda) nonCasted;
List<String> params = Collections.list(request.getParameterNames());
long cnt = params.stream().filter(p -> p.contains("[")).map(p -> p.substring(0, p.indexOf("]") + 1)).distinct().count();
if(cnt > 0) {
List<String> types = params.stream().filter(p -> p.startsWith("itemVenda") && p.endsWith("type")).map(p -> request.getParameter(p)).collect(Collectors.toList());
for(int i = 0; i < cnt; i++) {
try {
Class<? extends ItemVenda> clz = (Class<? extends ItemVenda>) Class.forName(ItemVenda.class.getPackage().getName() + "." + types.get(i));
if(CollectionUtils.isEmpty(ov.getItemVenda())) {
ov.setItemVenda(new ArrayList<>());
}
ov.getItemVenda().add(clz.newInstance());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
My question is: Is there a cleanner way of achieving the same result? Like some sort of custom property editor?
P.S.: I tried very very hard to use some custom property editors but they were never invoked by spring. I tried stuff like 'registerCustomEditor(ItemVenda.class, myEditor), registerCustomEditor(List.class, myEditor), registerCustomEditor(List.class, 'itemVenda', myEditor), registerCustomEditor(ItemVenda.class, 'itemVenda', myEditor), ..., ... but none of them worked.
Exception:
Invalid property 'itemVenda[0]' of bean class [com.richard.weger.rerp.domain.OrdemDeVenda]: Illegal attempt to get property 'itemVenda' threw exception; nested exception is org.springframework.beans.NullValueInNestedPathException: Invalid property 'itemVenda' of bean class [com.richard.weger.rerp.domain.OrdemDeVenda]: Could not instantiate property type [com.richard.weger.rerp.domain.ItemVenda] to auto-grow nested property path; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.richard.weger.rerp.domain.ItemVenda]: Is it an abstract class?; nested exception is java.lang.InstantiationException
org.springframework.beans.InvalidPropertyException: Invalid property 'itemVenda[0]' of bean class [com.richard.weger.rerp.domain.OrdemDeVenda]: Illegal attempt to get property 'itemVenda' threw exception; nested exception is org.springframework.beans.NullValueInNestedPathException: Invalid property 'itemVenda' of bean class [com.richard.weger.rerp.domain.OrdemDeVenda]: Could not instantiate property type [com.richard.weger.rerp.domain.ItemVenda] to auto-grow nested property path; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.richard.weger.rerp.domain.ItemVenda]: Is it an abstract class?; nested exception is java.lang.InstantiationException

Extending a table in Hibernate which has some relations

I have an Entity that would like to extend it by adding some fields. first of all they are not accessible to me to change directly, they are in their own jar file. here are the base entities:
#Entity
table(name="ACCOUNTDEF")
public class EtAccountDef
{
private String cNumber;
private List<EtAccount> accounts = new ArrayList();
public String getCNumber()
{
return cNumber;
}
public void setCNumber(String cNumber) {
this.cNumber = cNumber;
}
#OneToMany(fetch=FetchType.LAZY, cascade={javax.persistence.CascadeType.ALL}, mappedBy="accountDef")
public List<EtAccount> getAccounts() {
return accounts;
}
public void setAccounts(List<EtAccount> accounts) {
this.accounts = accounts;
}
}
which is the parent class and the below is child class:
#Entity
#Table(name="ACCOUNT")
public class EtAccount
{
private Double accountAmount;
private EtAccountDef accountDef;
private List<EtAccountItems> accountItems = new ArrayList();
#ManyToOne(fetch=FetchType.LAZY)
public EtAccountDef getAccountDef() {
return accountDef;
}
public void setAccountDef(EtAccountDef accountDef) {
this.accountDef = accountDef;
}
#OneToMany(fetch=FetchType.LAZY, cascade={javax.persistence.CascadeType.ALL}, mappedBy="account")
public List<EtAccountItems> getAccountItems() {
return accountItems;
}
public void setAccountItems(List<EtAccountItems> accountItems) {
this.accountItems = accountItems;
}
}
so I tried these changes to achieve my goal.
#MappedSuperclass
public abstract class OtAbstractAccount extends EtAccount {
private Double AccountCommission;
#Column(columnDefinition="decimal(15,2)")
public Double getAccountCommission() {
return accountCommission;
}
public void setAccountCommission(Double accountCommission) {
this.accountCommission = accountCommission;
}
and then extend it by this entity:
#Entity
#Table(name="ACCOUNT")
public class OtCostumAccount extends OtAbstractAccount {
}
The fields are now added to the base table(EtAccount) but
after compiling I get an error in the Weblogic that says:
Caused by: org.hibernate.AnnotationException: #OneToOne or #ManyToOne
on EtAccount.accountDef references an unknown entity: EtAccountDef
I have entered these two line in my ORM file:
<mapped-superclass class="package.OtAbstractAccount" />
<entity class="package.OtCostumAccount" />
Surprisingly when i comment
<mapped-superclass class="package.OtAbstractAccount" />
from ORM the weblogic does not rise any error but when I try to load object another error will be created that say:
Caused by: javax.persistence.PersistenceException:
org.hibernate.exception.SQLGrammarException: ORA-00904:
"OtCostumAccount "."DTYPE": invalid identifier
I'm confused whit these error and I'll appreciate any help.
If you can not modify the parent class, then the default hibernate inheritance strategy apply: one table per class. This strategy require a discriminant column which, by default, is DTYPE. Did you try to add a discriminator column to your OtCostumAccount entity or create the DTYPE column ?

How can I convert a Composite ID stored in a MongoDB into a Morphia Java entity object?

I have a problem when _id is a composite id. Then, I cannot convert it into a Morphia Java entity object.
The JSON in my MongoDB looks as follows:
{
"_id" : {
"id1" : "SAMPLE_ID1",
"id2" : "SAMPLE_ID2"
}
}
Java code:
import org.mongodb.morphia.annotations.Id;
#Entity(value = "MyCollection", noClassnameStored = true)
public class MyObject {
#Id
private MyObjectId thisId;
//....
}
public class MyObjectId{
#Property("id1")
private String id1;
#Property("id2")
private String id2;
//.....
}
I am using morphia v1.3.2.
When I insert the object, I get the following exception:
java.lang.RuntimeException: java.lang.ClassCastException: org.bson.types.ObjectId cannot be cast to com.mongodb.DBObject
at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:76)
at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:850)
at org.mongodb.morphia.mapping.Mapper.updateKeyAndVersionInfo(Mapper.java:725)
at org.mongodb.morphia.DatastoreImpl.postSaveOperations(DatastoreImpl.java:1422)
at org.mongodb.morphia.DatastoreImpl.postSaveOperations(DatastoreImpl.java:1408)
at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:1292)
at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:775)
at org.mongodb.morphia.DatastoreImpl.save(DatastoreImpl.java:758)
.......
When I select the object, I get the following exception:
java.lang.RuntimeException: java.lang.ClassCastException: org.bson.types.ObjectId cannot be cast to com.mongodb.DBObject
at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:76)
at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:850)
at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:282)
at org.mongodb.morphia.mapping.Mapper.fromDBObject(Mapper.java:193)
at org.mongodb.morphia.query.MorphiaIterator.convertItem(MorphiaIterator.java:134)
at org.mongodb.morphia.query.MorphiaIterator.processItem(MorphiaIterator.java:146)
at org.mongodb.morphia.query.MorphiaIterator.next(MorphiaIterator.java:117)
at org.mongodb.morphia.query.QueryImpl.asList(QueryImpl.java:147)
......
I have a very similar setup that I got working. I think all you'll need to do is add #Entity to MyObjectId, so
#Entity(noClassnameStored = true)
public class MyObjectId {
#Property("id1")
private String id1;
#Property("id2")
private String id2;
public MyObjectId() {
}
public MyObjectId(String id1, String id2) {
this.id1 = id1;
this.id2 = id2;
}
}
I seem to recall that the no-args constructor was required for marshalling.

QueryProjection with List as one of the parameters

I'm writing a query for the following domain model
#QueryEntity
public class Person
{
...
private String name;
private List<String> addresses;
...
}
And I wish to have the query result return to me a representation of a person as there are too much other fields that I do no care about.
public class PersonRepresentation
{
private string name;
private List<String> addresses;
#QueryProjection
public PersonRepresentation(String name, List<String> addresses){
this.name = name;
this.addresses = addresses;
}
...
}
When I attempt to create my JPA query as such
private final QPersonRepresentation qPersonRepresentationProjection = new QPersonRepresentation(
qPerson.name,
qPerson.addresses
);
List<PersonRepresentation> result = new JPAQuery(em)
.from(qPerson)
.list(qPersonRepresentationProjection);
I get the following error:
java.lang.IllegalArgumentException: org.hibernate.QueryException: not
an entity [select person.name,
person.addresses from
com.example.foo.Person person]
at
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1750)
at
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at
org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
at
org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:331)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
....
I've scurred both the documentation and the tests on the github and so far cannot come up with a reason why I cannot execute this query.

Spring BeanUtils couldn't instantiate generic class

I am trying to implement something for converting between my Entities and DTO.
I have base class for my DTOs (called Models):
public class BaseModel<Entity> implements Model<Entity> {
#Override
public Entity toEntity(Class<Entity> entityClass) {
Entity entityInstance = BeanUtils.instantiate(entityClass);
BeanUtils.copyProperties(this, entityInstance);
return entityInstance;
}
}
But following test doesn't passes:
public class BaseModelTest {
#Entity
public class SomeEntity {
#Id
private Long id;
private String name;
public SomeEntity() {
}
public SomeEntity(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
}
#Test
public void toEntity_givenEntityClass_shouldCreateNewInstance() throws Exception {
//given
BaseModel<SomeEntity> model = new BaseModel();
//when
SomeEntity entity = model.toEntity(SomeEntity.class);
//then
assertNotNull(entity);
}
}
I got exception: (despite the fact, under debugger I see all ctors):
org.springframework.beans.BeanInstantiationException: Failed to instantiate [package.BaseModelTest$SomeEntity]: Is it an abstract class?; nested exception is java.lang.InstantiationException: package.BaseModelTest$SomeEntity
Caused by: java.lang.InstantiationException: package.BaseModelTest$SomeEntity
Caused by: java.lang.NoSuchMethodException: package.BaseModelTest$SomeEntity.<init>()
Currently to create a new SomeEntity instance you need an instance of the enclosing BaseModelTest class. SomeEntity should be an inner static class. Replace:
public class SomeEntity {
with
public static class SomeEntity {
BTW. There is no point in having a DTO class if it maps 1-1 to a model class, it does not add any value, it is only boilerplate code.

Categories

Resources