I'm working with mongodb so I'm decoupling entities from presentation layer creating DTOs (with hibernate-validator annotations).
public abstract class UserDTO {
private String id;
#NotNull
protected String firstName;
#NotNull
protected String lastName;
protected UserType type;
protected ContactInfoDTO contact;
protected List<ResumeDTO> resumes;
public UserDTO(){}
//...
I'm trying to retrive from db this concrete class
public class UserType1DTO extends UserDTO {
private CompanyDTO company;
public UserType1DTO(){
super();
}
public UserType1DTO(String firstName, String lastName, ContactInfoDTO contact, CompanyDTO company) {
super(UserType.type1, firstName, lastName, contact);
this.company = company;
}
/...
Like this:
return mapper.map((UserType1) entity,UserType1DTO.class);
And I get this error about not being able to instanciate ResumeDTO
Failed to instantiate instance of destination *.dto.ResumeDTO. Ensure that *.dto.ResumeDTO has a non-private no-argument constructor.
ResumeDTO is similar to UserDTO, is an abstract class and has concrete classes for each user type. All they have constructors with no arguments.
What is the problem?
You are trying to map a concrete class to an abstract class, this will not work.
You can not use as destination an Abstract Class. Why? It can not be instantiated. So you must use a concrete class.
Definitively it wouldn't work a map with an Abstract Class destination:
mapper.map(entity, AbstractClass.class);
/*Error: java.lang.InstantiationException
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)*/
You must use a concrete class which extends the Abstract Class
public class ConcreteClass extends AbstractClass {
//
}
And then map it to this concrete class:
mapper.map(entity, ConcreteClass.class);
More info:
Due to it is not possible to instantiate an abstract class it will not work in destination properties neither.
There is an issue in Github related to this: https://github.com/jhalterman/modelmapper/issues/130
This error occurs when you have primitive data types or primitive return types in setter and getter or a parameterized constructor
so here you need to remove following code
public UserType1DTO(String firstName, String lastName, ContactInfoDTO contact,
CompanyDTO company) {
super(UserType.type1, firstName, lastName, contact);
this.company = company;
}
it will work fine.
What solved my issue is using typeMap and updating the version of ModelMapper. Please refer the below link:-
Mapping Lists with ModelMapper
Using typeMap still gave me the same error. Then I updated my ModelMapper version from 2.0.0 to 2.3.5, and the issue was resolved.
I was also getting the same exception. The way i resolved is made a private constructor of the destination class.
ViewDTO viewDto = (new ModelMapper()).map(object, ViewDTO.class);
The "object" is the domain object and it is to be mapped to the viewDto which is a DTO object to be sent to the client side.
I just added a private constructor to the ViewDTO class.
private ViewDTO() {}
and this solved my issue.And the verified answer also helped a lot.
Hope this is helpful.
Related
I'm creating dynamic collections by using mongoTemplate in service layer. Upto this everything went well but when saving into collection dynamically makes issue. explaining here...
Service Layer
public void createCollection(String collectionName) {
mongoTemplate.createCollection(collectionName);
}
public Object updateLessonOrSurveyOrQuery(String courseID, int levelNo, CourseAsset courseAssetToUpdate) {
.....
courseAssetRepo.saveByCourseID(courseID, courseAssetToUpdate);
.....
}
Repo Layer
#Repository
public interface CourseAssetRepo extends MongoRepository<CourseAsset, String> {
ArrayList<CourseAsset> findAllByCourseID(String courseID);
void saveByCourseID( String courseID, CourseAsset courseAsset);
}
findAllByCourseID working but saveByCourseID not woking;
POJO class
#Data
public class CourseAsset {
private int level;
private String title;
private String courseID;
}
ERROR :
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'courseAssetRepo' defined in com.dotbw.learn.repo.CourseAssetRepo defined in #EnableMongoRepositories declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration: Could not create query for public abstract void com.dotbw.learn.repo.CourseAssetRepo.saveByCourseID(java.lang.String,com.dotbw.learn.model.CourseAsset); Reason: No property 'saveByCourseID' found for type 'CourseAsset'
i can understand repo expects CourseAsset Data inside the pojo class. But while saving how we can provide this value.
i have tried many way as ChatGPT said but nothing worked.
I have a Spring MVC project using JPA which I have worked on for some time in the past without this issue. But now for some reason (likely an environmental issue as I have switch to a new laptop since I last worked on it) I am getting this weird error.
The project is essentially a tool for creating and performing surveys which are just a set of questions. There are multiple types of question such as "auto complete question", "multiple choice question", "integer question", etc which collect different types of data. Each of this question types is modeled by a subclass which extends an abstract class called DdmQuestion which looks something like this:
#Entity
#Table(name = "ddm_question")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "question_type")
#JsonIgnoreProperties({"dataType"})
#JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = JsonTypeInfo.As.PROPERTY, property = "#question_type")
#JsonSubTypes(value = { #Type(DdmTextQuestion.class),#Type(DdmDateQuestion.class),#Type(DdmTimeQuestion.class),#Type(DdmNumberIntegerQuestion.class),#Type(DdmChoiceMultiQuestion.class),#Type(DdmAutoCompleteQuestion.class) })
public abstract class DdmQuestion {
#Id
#GeneratedValue
#Column(name = "question_id")
private int questionId;
#Column(name = "name")
private String name;
public int getQuestionId() {
return questionId;
}
public void setQuestionId(int questionId) {
this.questionId = questionId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#JsonIgnore
public abstract String getDataType();
}
Note the getDataType() method.
Then, for each question type, I have a subclass extending this which looks something like this:
#Entity
#DiscriminatorValue("ddm_question_date")
public class DdmDateQuestion extends DdmQuestion {
final private String DATA_TYPE = "Long"; // this is the line with the error
#Override
public String getDataType() {
return DATA_TYPE;
}
}
Now, I've never encountered this error before (that I can recall) but Eclipse is throwing up an error here that says:
"The Java field for attribute "DATA_TYPE" is final". That's all it
says.
If I remove the #Entity annotation from the class, this error disappears so evidently something in JPA doesn't like something about this but I never had this error before so I'm thinking something changed in a newer version. My POM is not particularly explicit with dependency versions so this would not be surprising.
Can anyone explain to me why this is happening and what the correct resolution is? I could just remove the "final" from the field declaration but this seems wrong to me as it is definitely a final value...
Thanks in advance.
If it is a field that should not be persisted in the database you usually should take advantage of the transient annotation which would tell the persistence provider to ommit that field in its processing.:
#Transient
final private String DATA_TYPE = "Long";
If Eclipse is smart enough, it should stop highlighting the error altogether.
in this linkshttp://docs.oracle.com/javaee/5/tutorial/doc/bnbqa.html#Entities;
An entity class must follow these requirements:
The class must be annotated with the javax.persistence.Entity annotation.
The class must have a public or protected, no-argument constructor. The class may have other constructors.
The class must not be declared final. No methods or persistent instance variables must be declared final.
If an entity instance be passed by value as a detached object, such as through a session bean’s remote business interface, the class must implement the Serializable interface.
Entities may extend both entity and non-entity classes, and non-entity classes may extend entity classes.
Persistent instance variables must be declared private, protected, or package-private, and can only be accessed directly by the entity class’s methods. Clients must access the entity’s state through accessor or business methods.
I have this:
#Embeddable ClassA{
private String attributeA;
private String attributeB;
}
#Entity ClassB{
private String attributeC;
#Embedded ClassA extraAttrs;
}
Finally I have a CrudRepository from I want to get a query by using an attribute of ClassA, so I can't write this for example:
public interface TestCrud extends CrudRepository<ClassB, Long> {
public List<ClassB> findByAttributeA(String anA);
}
I can't do because attribute A is in the embedded ClassA instead off ClassB
How can I access from the CrudRepository interface definition to this attribute? Because this data it's in a single table, the purpose to put in a Embedded class it's because the attributes of ClassA are common to a lot of entitys, but not the PK, but now I need to access as I've said before.
Any ideas?
Thanks a lot to everyone who try to help me :),
This is actually very simple, you need to concat them together, in your case try this
findByExtraAttrsAttributeA(...)
In my Hibernate+Spring project I've got several entities quite similar; that's why I'm using inheritance type: Table Per Class. The thing is similar to this
class CommonEntity {
private Integer id;
private String name;
private String description;
// Constructors & Setters & Getters
}
class InheritedClass1 extends CommonEntity {
private boolean active;
// Constructors & Setters & Getters
}
class InheritedClass2 extends CommonEntity {
}
As I'm using XML mapping, the mapping for the 1st inherited class contains both CommonEntity and InheritedClass1 fields/columns.
Everything's fine so far.
Here the question is, what would be the best way to implement Repositories/DAOs for the inherited entities? As they will contain common fields (for instance, probably it would end up in implementing a findByName DAO method).
My main point is to avoid implement the same findByName for all inherited class as the only difference would be the name of the Named Query (i.e. InheritedClass1_FindByName and InheritedClass2FindByName).
You could use generics to make a single DAO method that would work for any class which extends your CommonEntity like this:
public <T extends CommonEntity > T getByName(Class<T> clazz, String name) {
Criteria crit = sessionFactory.getCurrentSession().createCriteria(clazz, "named");
crit.add(Restrictions.eq("named.name", name));
return (T)crit.uniqueResult();
}
Obviously if name is not unique you would need to call crit.list() rather than uniqueResult()
I have one abstract class and one concrete class.
abstract class FileModel{
public abstract void setName();
public abstract String getName();
}
class Container implements FileModel{
private String name;
#override
public void setName(String name){this.name=name;}
#override
public String getName(){return this.name;}
}
and my find method was like this:
public interface ContainerRepository extends
CrudRepository<Container, String>,
MongoRepository<Container, String>,
PagingAndSortingRepository<Container, String> {
#Query(value = "{ 'pid' : ?0,'status':{'$ne':'deletion'}}", fields = "{'name' : 1,'referenceId' : 1,'_class':1}")
List<FileModel> findByPid(String pid, Pageable pageable);
}
After I run the method findByPid,I got the following error:No property name found on FileModel . Is it necessary to add that property name in the abstract class? When back to spring-data-mongodb 1.0.4, all that code above worked fine. Now I just upgraded to 1.3.1, it broke. Anything that can workaround? Thanks.
After searching on st and some googling. I found some similar questions and did some coding,turns out all I need to do is moving all the private fields from the concrete class into the abstract class and make them protected except the #id idfield.Then all things on the go.