I want to know if it's possible to map a DTO to an entity class with a composite pk. I've been reading ModelMapper documentation about PropertyMap but I can't make it work.
Here is the code:
PlanDTO:
public class PlanDTO implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String formula;
private String frequency;
private String pricingtable;
// getters and setters omitted
PlanId:
#Embeddable
public class PlanId implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
public BillingPlanId() { }
public PlanId(Long id, String name) {
this.id = id;
this.name = name;
}
// getters and setters omitted
}
Plan:
#Entity
#Table(name = "plan")
public class Plan implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private PlanId id;
#Column(name = "formula")
private String formula;
#Column(name = "frequency")
private String frequency;
#Column(name = "pricingtable")
private String pricingTable;
public Plan() { }
//setters and getters omitted
}
Here is the ModelMapper configuration.
#Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setAmbiguityIgnored(true);
PropertyMap<PlanDTO, Plan> itemMap1 = new PropertyMap<PlanDTO, Plan>() {
protected void configure() {
map().setFormula(source.getFormula());
map().setFrequency(source.getFrequency());
map().setId(new Plan(source.getId(), source.getName()));
map().setPricingTable(source.getPricingtable());
}
};
modelMapper.addMappings(itemMap1);
}
But this happens at runtime debug image
Is there something wrong with the configuration? Do I miss something?
I am not quite sure what is your problem but mapping should be quite easy with a just one property mapping:
modelMapper.addMappings(new PropertyMap<PlanDTO, Plan>() {
#Override
protected void configure() {
map().getId().setName(source.getName());
}
});
All the other fields should be implicitly mapped by their name. Even the PlanId.id.
Related
I am not able to fetch all records from two tables using the below query
I have tried this but I am getting a result from one table only. I want a result of both the tables i.e, client_software_param_mapping and client_file_configuration having the same ClientId which is a foreign key from third pojo(client_software_configuration) to first and second pojo.
public Result showClientConfiguration() {EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("defaultPU");
EntityManager entityManager = entityManagerFactory.createEntityManager();
Query q=entityManager.
createQuery("SELECT c FROM client_software_param_mapping c JOIN fetch client_file_configuration f ON c.ClientId=f.ClientId");
List data =q.getResultList();
return ok(Json.toJson(data));
}
first pojo
#Entity
public class client_file_configuration {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String sourceFolder;
private String sourceFile;
private String processingFolder;
private String processingFile;
private String processedFolder;
private int intervalInMin;
private String readAfterDelay;
private String parserClass;
private String directoryMode;
private String fileMode;
private String actionMode;
private String type;
private String fileExpressionResolver;
#OneToOne
#JoinColumn(name = "ClientId")
private client_software_configuration clientSoftwareConfiguration;
public client_software_configuration getClientSoftwareConfiguration() {
return clientSoftwareConfiguration;
}
public void setClientSoftwareConfiguration(client_software_configuration clientSoftwareConfiguration) {
this.clientSoftwareConfiguration = clientSoftwareConfiguration;
}
}
secondpojo
#Entity
public class client_software_param_mapping {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String paramKey;
private String paramValue;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getParamKey() {
return paramKey;
}
public void setParamKey(String paramKey) {
this.paramKey = paramKey;
}
public String getParamValue() {
return paramValue;
}
public void setParamValue(String paramValue) {
this.paramValue = paramValue;
}
#ManyToOne
#JoinColumn(name = "ClientId")
private client_software_configuration clientSoftwareConfiguration;
public client_software_configuration getClientSoftwareConfiguration() {
return clientSoftwareConfiguration;
}
public void setClientSoftwareConfiguration(client_software_configuration clientSoftwareConfiguration) {
this.clientSoftwareConfiguration = clientSoftwareConfiguration;
}
}
thirdpojo
#Entity
public class client_software_configuration {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String url;
private int port;
private String endPoint;
private String isPost;
private String isPing;
private String params;
private int serialNo;
private String dateFormat;
private String token;
}
this is the right query as it is returning the object of the third pojo present at that ClientId so it is able to understand the type of ClientId.JPQL never uses table and column names. It always uses entity names and their mapped fields/properties names.so here I have taken the object of the third pojo having the ClientId field.
select c,p from client_file_configuration c,client_software_param_mapping p where c.clientSoftwareConfiguration = p.clientSoftwareConfiguration
I have a select statement that loads in the class Folders with a one-to-many relationship with File. While this sometimes happens without error, it sometimes gives me a Hibernate error saying that my use of session is unsafe, or that there were two representations of the same collection Folders.file. What am I doing wrong? Thanks for your help!
Folders.java
#Entity
#Table(name= "folders")
public class Folders implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "folder_code")
private Integer folderCode;
#Column(name = "assign_code")
private Integer assignCode;
public Set<File> getFile() {
return file;
}
public void setFile(Set<file> assignments) {
this.file = file;
}
#OneToMany(targetEntity=File.class,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
#JoinColumn(name="assign_code",referencedColumnName="assign_code")
Set<Folder> folder;
public Integer getAssignCode() {
return assignCode;
}
public void setAssignCode(Integer assignCode) {
this.assignCode = assignCode;
}
public Integer getFolderCode() {
return folderCode;
}
public void setFolderCode(Integer folderCode) {
this.folderCode = folderCode;
}
public Date retrieveFileStartDate(){
List<File> file;
if(this.getFile()!=null){
file= new ArrayList<File>(this.getFile());
}else{
file = new ArrayList<File>();
}
return file.size()>0 ? new
Date(file.get(0).getStartDate()): null;
}
}
File.java
#Entity
#Table(name= "file")
public class File implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "assign_code")
private Integer assignCode;
#Column(name = "start_date")
private String startDate;
#Column(name = "end_date")
private String endDate;
public Integer getAssignCode() {
return assignCode;
}
public void setAssignCode(Integer assignCode) {
this.assignCode = assignCode;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
}
I am not sure about the error you are getting but looking at your entities i can say that relationship mapping is not correct.
You are mapping #OneToMany in Folder entity but what about #ManyToOne in File entity?
also define mappedBy attribute to make it work expected.
Folder.java
#OneToMany(targetEntity=File.class,cascade=CascadeType.ALL,fetch=FetchType.EAGER,mappedBy="file")
#JoinColumn(name="assign_code",referencedColumnName="assign_code")
private Set<Folder> folder;
File.java
#ManyToOne
private File file;
//getter and setter
I am using Hibernate 4.3.8.Final and have problem with retrieving #Id property of lazy fetched property: For attached classes calling aidConfiguration.getChipApplication().getId() allways returns null. Other properties, eg. aidConfiguration.getChipApplication().getVersion() returns correctly the value from DB. If chipApplication is not lazy loaded (see the comment in the code), then aidConfiguration.getChipApplication().getId() returns correct non-null value.
What am I dong wrong?
BTW I need it to be lazy.
BaseEntity:
#MappedSuperclass
public class BaseEntity implements Serializable {
#Id
#Column(name = "ID", unique = true)
#Size(min = 1, max = 255)
private String id;
#PrePersist
public final void generateUuid() {
if (this.getId() == null) {
this.setId(UUID.randomUUID().toString());
}
}
public final String getId() {
return id;
}
public final void setId(final String id) {
this.id = id;
}
}
AidConfiguration:
#Entity
#Audited
public class AidConfiguration extends BaseEntity {
#Column
#NotBlank
private String name;
#NotNull
#ManyToOne(fetch = FetchType.LAZY) // if it is EAGER (defaut) then then aidConfiguration.getChipApplication().getId() returns correctly non-null value
private ChipApplication chipApplication;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "aidConfiguration", cascade = CascadeType.ALL) // cascade for auto-saving and deleting items
private List<AidConfigurationItem> aidConfigurationItems;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public ChipApplication getChipApplication() {
return chipApplication;
}
public void setChipApplication(final ChipApplication chipApplication) {
this.chipApplication = chipApplication;
}
public List<AidConfigurationItem> getAidConfigurationItems() {
return aidConfigurationItems;
}
public void setAidConfigurationItems(final List<AidConfigurationItem> aidConfigurationItems) {
this.aidConfigurationItems = aidConfigurationItems;
}
}
ChipApplication:
#Entity
#Audited
public class ChipApplication extends BaseEntity {
#Column
#NotBlank(message = "Aid can not be empty")
private String aid;
#Column
#NotBlank(message = "Product can not be empty")
private String product;
#Column
#NotBlank(message = "Version can not be empty")
private String version;
#NotNull(message = "Network is mandatory")
#ManyToOne(fetch = FetchType.LAZY)
private Network network;
#ManyToMany(fetch = FetchType.EAGER)
private List<AidTag> aidTags;
public String getAid() {
return aid;
}
public void setAid(final String aid) {
this.aid = aid;
}
public String getProduct() {
return product;
}
public void setProduct(final String product) {
this.product = product;
}
public String getVersion() {
return version;
}
public void setVersion(final String version) {
this.version = version;
}
public Network getNetwork() {
return network;
}
public void setNetwork(final Network network) {
this.network = network;
}
public List<AidTag> getAidTags() {
return aidTags;
}
public void setAidTags(final List<AidTag> aidTags) {
this.aidTags = aidTags;
}
}
Bit late, but the issue HH-9588 is still unresolved, and I just had the same issue (XML mapping rather than annotations, though).
Could not get the id from the getter when the binding was lazy. Got it when eager or fetch join.
Fixed it by getting rid of the "final" modifier on the getId() accessor. (final here was an attempt to protect the way primary keys/identifiers are defined in the superclass for all the entities)
before :
public abstract class Foo {
Long id;
public final Long getId() {
return id;
}
protected final void setId( Long id ){
this.id = id;
}
...
after :
public abstract class Foo {
Long id;
// No more final
public Long getId() {
return id;
}
// No more final
protected void setId( Long id ){
this.id = id;
}
...
Now, I can get the Id with a lazy binding as well.
Seems to me that this "final" modifier does not allow Hibernate to proxy this accessor as intended. The other accessors being not "final", one can access their values from the proxy.
So, I wonder whether HH-9588 is really a bug or a misunderstanding of the hibernate ways ?
That seems a bug, if you do not miss anything. I would report it on Hibernate's bug tracking system. It would be nice if you would update this answer afterwards with a link to the bug.
I'm trying to persist an entity that has a composite primary key but I get error :
12:59:48,221 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-56) SQL Error: 1110, SQLState: 42000
12:59:48,221 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-56) Column 'SENDERID' specified twice
I'm using EntityManager so I'm not sure where the 'SENDERID' is speciefied twice?
This is all the relevant classes:
Webservice:
#Path("friendservice")
public class FriendWebService {
#EJB
private FriendrequestFacade friendRequestFacade;
#GET
#Path("friendrequest")
#Produces(MediaType.TEXT_PLAIN)
public String insertFriendRequest(
#Context HttpServletRequest request){
String result = "false";
User user = (User) request.getSession().getAttribute("user");
User otherUser = (User) request.getSession().getAttribute("profileuser");
if((user != null) && (otherUser != null)){
if(user.getId() != otherUser.getId()){
System.out.println("Both users are alive.");
if(friendRequestFacade.insertFriendRequest(user, otherUser))
result = "true";
}
}
return result;
}
}
Facade:
#Stateless
public class FriendrequestFacade extends AbstractFacade<Friendrequest> {
#PersistenceContext(unitName = "FakebookPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public FriendrequestFacade() {
super(Friendrequest.class);
}
public boolean insertFriendRequest(User user, User otherUser){
Friendrequest fr = new Friendrequest();
FriendrequestPK frPK = new FriendrequestPK();
frPK.setSenderid(user.getId());
frPK.setReceiverid(otherUser.getId());
fr.setId(frPK);
em.clear();
em.persist(fr);
return true;
}
}
Entity:
#Entity
#XmlRootElement
#Table(name="FRIENDREQUEST")
#NamedQuery(name="Friendrequest.findAll", query="SELECT f FROM Friendrequest f")
public class Friendrequest implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private FriendrequestPK id;
#Temporal(TemporalType.TIMESTAMP)
private Date senddate;
//bi-directional many-to-one association to User
#ManyToOne
#JoinColumn(name="SENDERID")
private User user1;
//bi-directional many-to-one association to User
#ManyToOne
#JoinColumn(name="RECEIVERID")
private User user2;
public Friendrequest() {}
public FriendrequestPK getId() {
return this.id;
}
public void setId(FriendrequestPK id) {
this.id = id;
}
public Date getSenddate() {
return this.senddate;
}
public void setSenddate(Date senddate) {
this.senddate = senddate;
}
public User getUser1() {
return this.user1;
}
public void setUser1(User user1) {
this.user1 = user1;
}
public User getUser2() {
return this.user2;
}
public void setUser2(User user2) {
this.user2 = user2;
}
}
Composite Key:
#Embeddable
public class FriendrequestPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#Column(insertable=false, updatable=false)
private int senderid;
#Column(insertable=false, updatable=false)
private int receiverid;
public FriendrequestPK() {}
public FriendrequestPK(int senderid, int receiverid){
this.senderid = senderid;
this.receiverid = receiverid;
}
public int getSenderid() {
return this.senderid;
}
public void setSenderid(int senderid) {
this.senderid = senderid;
}
public int getReceiverid() {
return this.receiverid;
}
public void setReceiverid(int receiverid) {
this.receiverid = receiverid;
}
}
What am I doing wrong?
First of all please let me clarify that I rarely use #EmbeddedId so I could be missing something. That being told, the error is telling you that SENDERID column is specified twice: first time in your entity and then in the composite key. The same is probably happening with RECEIVERID too.
Entity
public class Friendrequest implements Serializable {
...
#EmbeddedId
private FriendrequestPK id;
#ManyToOne
#JoinColumn(name="SENDERID") // Column = SENDERID
private User user1;
#ManyToOne
#JoinColumn(name="RECEIVERID") // Column = RECEIVERID
private User user2;
...
}
Composite key
public class FriendrequestPK implements Serializable {
...
#Column(insertable=false, updatable=false)
private int senderid; // Column = SENDERID
#Column(insertable=false, updatable=false)
private int receiverid; // Column = RECEIVERID
...
}
According to Mapping identifier properties section in Hibernate Annotations reference guide, the entity mapping should be done using #MapsId annotation:
public class Friendrequest implements Serializable {
...
#EmbeddedId
private FriendrequestPK id;
#MapsId("senderid") // senderid = Field in FriendrequestPK class
#ManyToOne
private User user1;
#MapsId("receiverid") // receiverid = Field in FriendrequestPK class
#ManyToOne
private User user2;
...
}
I have two pojos.
public class Pojo1 implements Serializable {
private static final long serialVersionUID = 1302290920579795856L;
private Long id;
private String idNumber;
private String vendorNumber;
private Date expires;
// Getters and setters for each one
}
public class Pojo2 implements Serializable {
private static final long serialVersionUID = 1302290920579795856L;
private Long id;
private String idNumber;
private String vendorNumber;
private Date expires;
private String otherData;
// Getters and setters for each one
}
Is there a Java API that I can use to create a Pojo1 from a Pojo2 automatically?
I.e.:
Pojo1 newPojo1 = SomeLibrary.fromPojoWithLikeNamedFields(pojo2);
// newPojo1 now has all the fields that had the same name from pojo2
won't a copy constructor do the job?,
public Pojo1(Pojo2 pojo2){
this.id = pojo2.getId();
this.idNumber = pojo2.getIdNumber();
this.vendorNumber = pojo2.getVendorNumber();
this.expires = pojo2.getExpires();
}
and then use as such,
Pojo1 newPojo1 = new Pojo1(pojo2);
or am I misunderstanding something...?