EclipseLink EntityManager SQL JOIN on two tables - java

I have 2 different tables: subjects and questions and I need to make SQL JOIN on these 2 tables. Table subjects has its attributes: name and shortcut. Table questions has its attributes: question_number, text, subject - in fact, subject from table questions is a shortcut of a subject.
I tried something like this, what I saw in one stackoverflow topic:
Query q = em.createNativeQuery("SELECT q.question_number, q.text, s.name, s.shortcut FROM "
+ "( questions q INNER JOIN subjects s ON q.subject=s.shortcut );", QuestionSubject.class);
QuestionSubject.class is an #Entity class and has attributes of both questions table and subjects table. After calling this method I saw that a new table with a name QUESTIONSUBJECT was created in my database and that is what I do not want to be done.
Can anyone help me with other solution?
P.S.: I am doing this in order to use the ouput as a response on HTTP request so I need to gather those two into one. I need to return either a List or JSON string.
EDIT: Using MySQL database.
questions table Entity class:
package model;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "questions")
#XmlRootElement
public class Question implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Basic(optional = false)
#Column(name = "question_number")
private Integer questionNumber;
#Column(name = "text")
private String text;
#Column(name = "subject")
private String subject;
public Question() {
}
public Question(Integer questionNumber) {
this.questionNumber = questionNumber;
}
public Question( String text, String subject) {
this.text = text;
this.subject = subject;
}
public Question(Integer questionNumber, String text, String subject) {
this.questionNumber = questionNumber;
this.text = text;
this.subject = subject;
}
public Integer getQuestionNumber() {
return questionNumber;
}
public void setQuestionNumber(Integer questionNumber) {
this.questionNumber = questionNumber;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
#Override
public int hashCode() {
int hash = 0;
hash += (questionNumber != null ? questionNumber.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Question)) {
return false;
}
Question other = (Question) object;
if ((this.questionNumber == null && other.questionNumber != null) || (this.questionNumber != null && !this.questionNumber.equals(other.questionNumber))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Rest.Questions[ questionNumber=" + questionNumber + " ]";
}
}
subjects table Entity class.
package model;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "subjects")
#XmlRootElement
public class Subject implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 5)
#Column(name = "shortcut")
private String shortcut;
#Basic(optional = false)
#NotNull
#Lob
#Size(min = 1, max = 65535)
#Column(name = "name")
private String name;
public Subject() {
}
public Subject(String shortcut) {
this.shortcut = shortcut;
}
public Subject(String shortcut, String name) {
this.shortcut = shortcut;
this.name = name;
}
public String getShortcut() {
return shortcut;
}
public void setShortcut(String shortcut) {
this.shortcut = shortcut;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public int hashCode() {
int hash = 0;
hash += (shortcut != null ? shortcut.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Subject)) {
return false;
}
Subject other = (Subject) object;
if ((this.shortcut == null && other.shortcut != null) || (this.shortcut != null && !this.shortcut.equals(other.shortcut))) {
return false;
}
return true;
}
#Override
public String toString() {
return "Rest.Subjects[ shortcut=" + shortcut + " ]";
}
}
QuestionSubject Entity class:
package model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class QuestionSubject implements Serializable
{
#Id
#Column(name = "question_number")
private Integer questionNumber;
#Column(name = "text")
private String text;
#Column(name = "shortcut")
private String shortcut;
#Column(name = "name")
private String name;
public Integer getQuestionNumber() {
return questionNumber;
}
public void setQuestionNumber(Integer questionNumber) {
this.questionNumber = questionNumber;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getShortcut() {
return shortcut;
}
public void setShortcut(String shortcut) {
this.shortcut = shortcut;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

The table gets created because you define a class named QuestionSubject annotated as #Entity. Per default the table name is the class name.
You could override the name like you did in Subjects with #Table(name = "subjects")
Nearly the same would happen if you would define a #ManyToMany mapping on related fields between classes Question and Subject without defining QuestionSubject class at all.
I would recommend to take a look here to get more information:
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Mapping/Relationship_Mappings/Collection_Mappings/ManyToMany
Edit
If you need a manyToMany mapping you need this table. Otherwise you can only have an oneToMany resp. manyToOne relation (using foreign keys).

Related

Quarkus Hibernate: Entity not updated when changed value provided via method

I use Quarkus + Hibernate to sync data to the DB and I've noticed during testing that sometimes my entity isn't updated. I've created a minimal example adjusting the original example https://github.com/quarkusio/quarkus-quickstarts/tree/main/hibernate-orm-quickstart
Here are my adjustments:
import.sql
DROP TABLE IF EXISTS fruit CASCADE;
CREATE TABLE fruit (
fruitsSequence INT PRIMARY KEY,
name TEXT NOT NULL,
test INT
);
Fruit.java
package org.acme.hibernate.orm;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.google.common.base.Objects;
#Entity
#Table(name = "known_fruits")
public class Fruit {
#Id
#SequenceGenerator(name = "fruitsSequence", sequenceName = "known_fruits_id_seq", allocationSize = 1, initialValue = 10)
#GeneratedValue(generator = "fruitsSequence")
private Integer id;
#Transient
private String name = "";
#Column(name = "test")
private Integer test = -1;
public Fruit() {
}
public Fruit(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name")
#Access(AccessType.PROPERTY)
public String getChangedName() {
return "a" + name;
}
public String getName() {
return name;
}
public void setTest(Integer test) {
this.test = test;
}
public Integer getTest() {
return test;
}
#Column(name = "name")
#Access(AccessType.PROPERTY)
protected void setChangedName(String name) {
this.name = name.substring(1);
}
public void setName(String name) {
this.name = name;
}
#Override
public int hashCode() {
return Objects.hashCode(name, test);
}
#Override
public boolean equals(Object o) {
if (o instanceof Fruit) {
Fruit other = (Fruit) o;
return name.equals(other.name) && test.equals(other.test);
}
return false;
}
}
Replaced the test withDBTest.java
package org.acme.hibernate.orm;
import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.assertEquals;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.UserTransaction;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
#QuarkusTest
public class DBTest {
#Inject
EntityManager m_em;
#Inject
UserTransaction m_transaction;
#Test
void testUpdate() throws Exception {
Fruit fruit = given().when().body("{\"name\" : \"Pear\"}").contentType("application/json").post("/fruits")
.then().statusCode(201).extract().as(Fruit.class);
m_transaction.begin();
Fruit db = m_em.find(Fruit.class, fruit.getId());
db.setName("Apple");
db.setTest(13);
m_transaction.commit();
db = m_em.find(Fruit.class, fruit.getId());
assertEquals(13, db.getTest(), "Unexpected test");
assertEquals("Apple", db.getName(), "Unexpected name");
}
#Test
void testUpdateLongName() throws Exception {
Fruit fruit = given().when().body(
"{\"name\" : \"PeeeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaDBaaaaaaaaaaaaaar\"}")
.contentType("application/json").post("/fruits").then().statusCode(201).extract().as(Fruit.class);
m_transaction.begin();
Fruit db = m_em.find(Fruit.class, fruit.getId());
db.setName(fruit.getName() + "Apple");
db.setTest(13);
m_transaction.commit();
db = m_em.find(Fruit.class, fruit.getId());
assertEquals(13, db.getTest(), "Unexpected test");
assertEquals(fruit.getName() + "Apple", db.getName(), "Unexpected name");
}
#Test
void testUpdateNameOnly() throws Exception {
Fruit fruit = given().when().body("{\"name\" : \"Pear\"}").contentType("application/json").post("/fruits")
.then().statusCode(201).extract().as(Fruit.class);
m_transaction.begin();
Fruit db = m_em.find(Fruit.class, fruit.getId());
db.setName("Apple");
m_transaction.commit();
db = m_em.find(Fruit.class, fruit.getId());
assertEquals(-1, db.getTest(), "Unexpected test");
assertEquals("Apple", db.getName(), "Unexpected name");
}
#Test
void testUpdateNameOnlyREST() throws Exception {
Fruit fruit = given().when().body("{\"name\" : \"Pear\"}").contentType("application/json").post("/fruits")
.then().statusCode(201).extract().as(Fruit.class);
given().when().body("{\"name\" : \"Apple\"}").contentType("application/json").put("/fruits/" + fruit.getId())
.then().statusCode(200).extract().as(Fruit.class);
Fruit db = m_em.find(Fruit.class, fruit.getId());
assertEquals(-1, db.getTest(), "Unexpected test");
assertEquals("Apple", db.getName(), "Unexpected name");
}
}
What I see is that testUpdateNameOnly and testUpdateNameOnlyREST fail whereas the other tests run as expected. In my original testcase, even changing another field didn't update the TEXT field hence the test with the long name. The reason why the name is altered when writing it to the DB is to encrypt it (the outcome is a BASE64 string).
I am not sure if this is a configuration issue or an actual bug.
Thanks for helps in advance!
As suggested by the comments this seems to be a bug (https://github.com/quarkusio/quarkus/issues/16619).
It works with the AttributeConver:
Fruit.java:
package org.acme.hibernate.orm;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import com.google.common.base.Objects;
#Entity
#Table(name = "known_fruits")
public class Fruit {
#Id
#SequenceGenerator(name = "fruitsSequence", sequenceName = "known_fruits_id_seq", allocationSize = 1, initialValue = 10)
#GeneratedValue(generator = "fruitsSequence")
private Integer id;
#Column(name = "name")
#Convert(converter = NameConverter.class)
private String name = "";
#Column(name = "test")
private Integer test = -1;
public Fruit() {
}
public Fruit(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setTest(Integer test) {
this.test = test;
}
public Integer getTest() {
return test;
}
public void setName(String name) {
this.name = name;
}
#Override
public int hashCode() {
return Objects.hashCode(name, test);
}
#Override
public boolean equals(Object o) {
if (o instanceof Fruit) {
Fruit other = (Fruit) o;
return name.equals(other.name) && test.equals(other.test);
}
return false;
}
}
NameConverter.java:
package org.acme.hibernate.orm;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
#Converter
public class NameConverter implements AttributeConverter<String, String> {
#Override
public String convertToDatabaseColumn(String name) {
return "a" + name;
}
#Override
public String convertToEntityAttribute(String name) {
return name.substring(1);
}
}

Sorting with model reference on PageRequest not working

I am using Spring data PageRequest to search data based on user filter. I need my sort column to be dynamic along with search filters.
However stateMaster.countryMaster.description, stateMaster.description, description code is not working and throws following error.
org.springframework.data.mapping.PropertyReferenceException: No property description, stateMaster found for type CountryMaster! Traversed path: DistrictMaster.stateMaster.countryMaster.
Here's my service code.
String sortColumn = filterJson.getString("sortColumn");
if ("default".equalsIgnoreCase(filterJson.getString("sortColumn"))) {
sortColumn = "stateMaster.countryMaster.description, stateMaster.description, description";
} else {
sortColumn = "description";
}
String sortOrder = filterJson.getString("sortOrder");
Integer maxResult = Integer.parseInt(hbsService.getGeneralConfigValue("adminmaxallowedlisting"));
PageRequest pageRequest = new PageRequest(pageNo, maxResult, Sort.Direction.valueOf(sortOrder), sortColumn);
Page<DistrictMaster> page = districtRepository.findAll(new Specification<DistrictMaster>() {
#Override
public Predicate toPredicate(Root<DistrictMaster> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
if (filterJson.optLong("stateId") != 0) {
predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("stateMaster"), filterJson.optLong("stateId"))));
}
if (!filterJson.optString("status").trim().isEmpty() && !filterJson.optString("status").equals("All")) {
predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("active"), filterJson.optBoolean("status"))));
}
if (!filterJson.optString("value").trim().isEmpty()) {
predicates.add(criteriaBuilder.and(criteriaBuilder.like(criteriaBuilder.lower(root.get("description")), "%" + filterJson.optString("value").toLowerCase() + "%")));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
}, pageRequest);
Here's my model:
package com.agrisk.data.model;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
#Entity
#Table(name = "tbldistrictmst")
#SequenceGenerator(name = "districtmstseq", allocationSize = 1, sequenceName = "districtmstseq")
public class DistrictMaster extends MakerCheckerBO implements Serializable {
/**
*
*/
private static final long serialVersionUID = 5461420398663313529L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "districtmstseq")
#Column(name = "id")
public Long id;
#Column(name = "description")
public String description;
#Column(name = "code")
public String code;
#ManyToOne
#JoinColumn(name = "stateid")
private StateMaster stateMaster;
#Column(name = "active")
public Boolean active;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "districtid")
public Set<TehsilMaster> tehsilMaster;
#Column(name = "villagereferenceid")
private Long villageReferenceId;
public Set<TehsilMaster> getTehsilMaster() {
return tehsilMaster;
}
public void setTehsilMaster(Set<TehsilMaster> tehsilMaster) {
this.tehsilMaster = tehsilMaster;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public StateMaster getStateMaster() {
return stateMaster;
}
public void setStateMaster(StateMaster stateMaster) {
this.stateMaster = stateMaster;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public Long getVillageReferenceId() {
return villageReferenceId;
}
public void setVillageReferenceId(Long villageReferenceId) {
this.villageReferenceId = villageReferenceId;
}
}

How to enum mapping with jpa Spring boot why not save enum value in DB in DB saving enum key

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
import org.hibernate.annotations.GenericGenerator;
import com.lue.billingsystem.enums.Status;
import com.lue.billingsystem.enums.Types;
#Entity
#Table(name="product_tab")
public class Product implements Serializable{
private static final long serialVersionUID = 8919320309645697466L;
#Id
#Column(name="prod_id",updatable=false)
#GenericGenerator(name="product_tab_genetator",strategy="increment")
#GeneratedValue(generator="product_tab_genetator")
private Long id;
private String name;
#Enumerated(EnumType.STRING)
#Column(name = "type")
private Types type;
#Column(name = "status")
#Enumerated(EnumType.STRING)
private Status status;
#Column(name = "description", length = 200)
private String description;
#OneToMany(mappedBy="product")
private List<Charge> charges;
#Column(name = "create_date", columnDefinition = "DATETIME")
private Date createDate;
#Column(name = "update_date", columnDefinition = "DATETIME")
private Date updateDate;
//#Version
private Integer version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Types getType() {
return type;
}
public void setType(Types type) {
this.type = type;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Charge> getCharges() {
return charges;
}
public void setCharges(List<Charge> charges) {
this.charges = charges;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
import org.springframework.http.HttpStatus;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.lue.billingsystem.enums.utils.StatusDeserializer;
import com.lue.billingsystem.exception.BillingException;
#JsonDeserialize(using = StatusDeserializer.class)
public enum Status {
ACTIVE("Active"), INACTIVE("Inactive");
private final String text;
Status(final String text) {
this.text = text;
}
#Override
public String toString() {
return text;
}
public String getText() {
return this.text;
}
public static Status fromText(String text) {
for (Status r : Status.values()) {
if (r.getText().equals(text)) {
System.out.println(r);
return r;
}
}
throw new BillingException("Your Status not valied: "+text +" ", HttpStatus.BAD_REQUEST, 400);
}
}
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.lue.billingsystem.enums.Status;
public class StatusDeserializer extends JsonDeserializer<Status> {
#Override
public Status deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
if (node == null) {
return null;
}
String text = node.textValue(); // gives "A" from the request
if (text == null) {
return null;
}
//System.out.println(Status.fromText(text) + "---------------");
return Status.fromText(text);
}
}
How to enum mapping with jpa Spring boot why not save enum value in DB in DB saving enum key when i saving product in databse not save status like Active it always save ACTIVE
You just need to pay attention to the enum values when the table is being created.
What are the enum values in the table e.g. in status column, are the values defined as 'Active', 'Inactive' or 'ACTIVE', 'INACTIVE'. That's what will determine the value saved.
If the enum values are defined as 'ACTIVE', 'INACTIVE', if you insert 'active' as the value for status, it will change to 'ACTIVE' inside the database because it inserts based on the pre defined enum values.

Hibernate AnnotationException: mappedBy reference

There are lots of questions about this in StackOverflow. But l still can't solve it.
I am coding a tax system using Hibernate as my persistence layer.
Now, l have two entity classes:
Role.java and RolePrivilege.java.
this is Role.java
package com.taxsys.nsfw.role.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
#Entity
#Table(name="role")
public class Role implements Serializable{
#Id
#GenericGenerator(name="pk_hilo", strategy="hilo")
#GeneratedValue(generator="pk_hilo")
#Column(name="role_id")
private String roleId;
#Column(name="role_name",length=32, nullable=false)
private String roleName;
#Column(name="state", length=1)
private String state;
#OneToMany(targetEntity=RolePrivilege.class,
mappedBy="role", cascade=CascadeType.ALL,
fetch=FetchType.EAGER)
private Set<RolePrivilege> role = new HashSet<>();
public static String ROLE_STATE_VALID = "1";
public static String ROLE_STATE_INVALID = "0";
public Set<RolePrivilege> getRolePrivilege() {
return role;
}
public void setRolePrivilege(Set<RolePrivilege> rolePrivilege) {
this.role = rolePrivilege;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Role() {
}
public Role(String roleId, String roleName, String state, Set<RolePrivilege> rolePrivilege) {
super();
this.roleId = roleId;
this.roleName = roleName;
this.state = state;
this.role = rolePrivilege;
}
}
this is RolePrivilege.java:
package com.taxsys.nsfw.role.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="role_privilege")
public class RolePrivilege implements Serializable{
#ManyToOne(targetEntity=Role.class, fetch=FetchType.EAGER)
#JoinColumn(name="role_id", referencedColumnName="role_id")
#Id
private Role role;
#Id
private String code;
public RolePrivilege(Role role, String code) {
super();
this.role = role;
this.code = code;
}
public RolePrivilege() {
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((code == null) ? 0 : code.hashCode());
result = prime * result + ((role == null) ? 0 : role.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RolePrivilege other = (RolePrivilege) obj;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
if (role == null) {
if (other.role != null)
return false;
} else if (!role.equals(other.role))
return false;
return true;
}
}
I am using Hibernate3.6,spring3.0,struts2.3 and tomcat7.
But when l start Tomcat, the error message will be showing:
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.taxsys.nsfw.role.entity.RolePrivilege.role in com.taxsys.nsfw.role.entity.Role.role
Look my code! mappedBy="role".It's the same with RolePrivilege.role!And even if l use lower-case, it doesn't work! I don't know why. Maybe it is a question about jar or compatibility? Thank you!
Remove #Id in RolePrivilege.java for private Role role; and report back what error are u still getting
You can map the composite key using #Embeddable annotation in a new class object, then use #ManyToOne mapping to map the child object to the parent object. See Hibernate annotations to map one to one unidirectional association with composite primary key

Join in hibernate with annotaion

I am trying to perform join in hibernate and i am using struts2.
I am working with hibernate using annotaions. Now i am unable to perform join between two tables.My first table is "studentprojects" which contain pid and email.Second table is "initialprojectdetials" which contains pid,name,description... similarly some other fields.I have to get the data of second table by performing join around pid of first table.
For this am using this query:
String hql="from InitialProjectDTO I join I.projectId S where I.projectId=:id";
Query query=session.createQuery(hql);
query.setParameter("id", id);
mail =query.list();
where mail is the arraylist of InitialProjectDTO.
And my InitialProjectDTO is:
package edu.pma.dto;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="initialprojectdetail")
public class InitialProjectDTO {
#Id
#Column(name="projectId")
#OneToMany(cascade=CascadeType.ALL)
#JoinTable(name="studentprojects",joinColumns=#JoinColumn(name="projectId"))
int projectId;
#Column(name="name")
String name;
#Column(name="description")
String description;
#Column(name="technology")
String technology;
#Column(name="guide")
String guide;
#Column(name="duration")
int duration;
#Column(name="status")
String status;
#Column(name="report")
String report;
public String getReport() {
return report;
}
public void setReport(String report) {
this.report = report;
}
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTechnology() {
return technology;
}
public void setTechnology(String technology) {
this.technology = technology;
}
public String getGuide() {
return guide;
}
public void setGuide(String guide) {
this.guide = guide;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
my SudentProjectDTO is:
package edu.pma.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="studentprojects")
public class StudentProjectDTO {
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
#Id
#Column(name="email")
String email;
#Column(name="projectId")
int projectId;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
This is the error which i am getting:
Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements: edu.pma.dto.InitialProjectDTO.projectId
Method "execute" failed for object edu.pma.actions.LoginAction#1096a56
File: org/hibernate/cfg/annotations/CollectionBinder.java
You should try to use different models
#Entity
public class InitialProjectDTO {
#OneToMany(mappedBy = "project")
private Collection<StudentProjectDTO> students;
}
#Entity
public class StudentProjectDTO {
#ManyToOne
private InitialProjectDTO project;
}
And with the proper model it shuld be easy to write hql, you might want to look here for examples https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html.
Also I would suggest to look here for example of models. http://viralpatel.net/blogs/hibernate-one-to-many-annotation-tutorial/
See following example might its help to you
#Entity
#Table(name="initialprojectdetail")
public class InitialProjectDTO {
private Integer initialProjectDTOId;
private Set<StudentProjectDTO > studentProjectDTO = new HashSet<StudentProjectDTO >(0);
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "initial_projectDTO_id", unique = true, nullable = false)
public Integer getInitialProjectDTOId() {
return this.initialProjectDTOId;
}
public void setInitialProjectDTOId(Integer initialProjectDTOId) {
this.initialProjectDTOId = initialProjectDTOId;
}
#OneToMany(mappedBy = "studentprojects", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
public Set<StudentProjectDTO> getUserRole() {
return this.studentProjectDTO;
}
public void setUserRole(Set<StudentProjectDTO> studentProjectDTO) {
this.studentProjectDTO = studentProjectDTO;
}
}
#Entity
#Table(name="studentprojects")
public class StudentProjectDTO {
private InitialProjectDTO project;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "initial_projectDTO_id", nullable = false)
public User getProject() {
return this.project;
}
public void setProject(InitialProjectDTO project) {
this.project = project;
}
}
your Query shoud be something like this
String hql="SELECT ip from InitialProjectDTO ip JOIN ip.studentProjectDTO sp WHERE sp.projectId = :id";
Query query=session.createQuery(hql);
query.setParameter("id", id);
mail =query.list();

Categories