I have a Canteen class and a Course class (and a BaseEntity). The Canteen class has a set of courses. A course is unique if the composition of name, dateOfServing and the canteen id is unique. I tried to write a test case which should throw an exception if a non-unique course is added to a canteen. But the test doesn't throw any exception at all. Which leads me to believe that I'm doing me Canteen and Course class wrong. The test in question is addDuplicatedCourseToCanteenTest. Anyone got a clue about what I'm doing wrong?
I'm new to TDD as well so any critique in that area is very welcome as well.
BaseEntity.java
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
long id;
private Date createdAt;
private Date updatedAt;
// TODO: http://stackoverflow.com/a/11174297/672009
// Using the above we wouldn't have to created a CommentRepository
// Is that a good idea?
/**
* http://www.devsniper.com/base-entity-class-in-jpa/
*/
/**
* Sets createdAt before insert
*/
#PrePersist
public void setCreationDate() {
this.setCreatedAt(new Date());
}
/**
* Sets updatedAt before update
*/
#PreUpdate
public void setChangeDate() {
this.setUpdatedAt(new Date());
}
public Date getCreatedAt() {
return createdAt;
}
protected void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
protected void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseEntity other = (BaseEntity) obj;
if (id != other.id)
return false;
return true;
}
}
Canteen.java
#Entity
public class Canteen extends BaseEntity {
private String name;
// TODO: https://schuchert.wikispaces.com/JPA+Tutorial+1+-+Embedded+Entity
// http://docs.oracle.com/javaee/6/api/javax/xml/registry/infomodel/PostalAddress.html
//private Address address;
//private PostalAddress postalAddress;
/**
* In honor of KISS I simply use a simple string address as a holder for the restaurants address.
* The idea is that the string will contain an address which will be valid according to google maps.
* Same goes for openingHours, phoneNumber and homepage... KISS wise.
*/
private String address;
private String openingHours; // A string which will be presented within a pre tag
// Eg. <pre>Mandag - Torsdag 10-22
// Fredag - Lørdag 10-24
// Søndag 11-20</pre>
private String contact;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Course> courses = new HashSet<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getOpeningHours() {
return openingHours;
}
public void setOpeningHours(String openingHours) {
this.openingHours = openingHours;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
public boolean addCourse(Course course)
{
return getCourses().add(course);
}
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Canteen other = (Canteen) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Course.java
#Entity
public class Course extends BaseEntity {
private String name;
private Date dateOfServing;
#ManyToOne
private Canteen canteen;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDateOfServing() {
return dateOfServing;
}
public void setDateOfServing(Date dateOfServing) {
this.dateOfServing = dateOfServing;
}
public Canteen getCanteen() {
return canteen;
}
public void setCanteen(Canteen canteen) {
this.canteen = canteen;
}
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((canteen == null) ? 0 : canteen.hashCode());
result = prime * result
+ ((dateOfServing == null) ? 0 : dateOfServing.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Course other = (Course) obj;
if (canteen == null) {
if (other.canteen != null)
return false;
} else if (!canteen.equals(other.canteen))
return false;
if (dateOfServing == null) {
if (other.dateOfServing != null)
return false;
} else if (!dateOfServing.equals(other.dateOfServing))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
CanteenHasCoursesTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = PersistenceConfig.class)
public class CanteenHasCoursesTest {
#Autowired
private CanteenRepository canteenRepository;
private String canteenName;
private String courseName;
private Canteen canteen;
private Course course;
#Before
public void setUp() {
// Generate unique random name
canteenName = UUID.randomUUID().toString();
// Generate unique random name
courseName = UUID.randomUUID().toString();
// Create new canteen
canteen = new Canteen();
canteen.setName(canteenName);
// Create new course
course = new Course();
course.setName(courseName);
}
#Test
public void addCourseToCanteenTest() {
// Add course
canteen.addCourse(course);
// Save canteen
canteenRepository.save(canteen);
// Find it again
Canteen c = canteenRepository.findOne(canteen.getId());
// Confirm attributes are as expected
assertNotNull(c);
Set<Course> courses = c.getCourses();
Iterator<Course> it = courses.iterator();
assertTrue(it.hasNext());
Course course = it.next();
assertEquals(courseName, course.getName());
}
// TODO: expect some data violation exception
// #Test(expected = IndexOutOfBoundsException.class)
#Test
public void addDuplicatedCourseToCanteenTest() {
// Add course
canteen.addCourse(course);
// Add it again
canteen.addCourse(course);
// Save canteen
canteenRepository.save(canteen);
}
#After
public void tearDown() {
canteenRepository = null;
canteenName = null;
courseName = null;
canteen = null;
course = null;
}
}
Related
I have actually a problem on a Set in my project (code below)
public static Set<BeanObject> mapToSetBean(Collection<Object> listModel) {
Set<BeanObject> listToReturn = new HashSet<>();
for (Iterator<Object> iterator = listModel.iterator(); iterator.hasNext();) {
Object model = iterator.next();
BeanObject bean = new BeanObject();
bean = mapToBean(model);
listToReturn.add(bean);
}
return listToReturn;
}
When some beans are added to the list they replace another one.
For example:
List{}
add object1 / List{object1}
add object2 / List{object1, object2}
add object1 / List{object1, object2, object3}
add object4 / List{object4, object2, object3}
The equals and the hashcode of the object are override the hashcode are all different and in debug mode we don't enter in the override equals.
When I use an ArrayList everything works but I prefer not to change the type it has a huge impact on my project.
---------------- EDIT ---------------
public static BeanObject mapToBean(Object model) {
BeanObject bean = new BeanObject();
if (model != null) {
bean.setId(model.getId());
if(model.getId() != null){
bean.setIdString(model.getId().toString());
}
if (model.getName() != null) {
bean.setName(model.getName().toLowerCase());
}
bean.setActif(model.getActif());
if (model.getShortName() != null) {
bean.setShortName(model.getShortName().toUpperCase());
}
}
return bean;
}
BeanObject
public class BeanObject implements Comparable<BeanObject> {
/**
* serial
*/
private static final long serialVersionUID = 1L;
private BigInteger id;
private String name;
private String shortName;
private Short actif;
private String idString;
public BeanObject() {
}
public BeanObject(BigInteger id, String libelle) {
this.id = id;
this.name = libelle;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!(o instanceof BeanObject)) {
return false;
}
BeanObject other = (BeanObject) o;
boolean result;
if (null == this.id) {
if (null == other.id) {
result = true;
} else {
result = false;
}
} else {
result = this.id.equals(other.id);
}
return result;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
return this.id.intValue() * name.hashCode() * shortName.hashCode();
}
public BigInteger getId() {
return id;
}
public void setId(BigInteger id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public Short getActif() {
return actif;
}
public void setActif(Short actif) {
this.actif = actif;
}
public String getIdString() {
return idString;
}
public void setIdString(String idString) {
this.idString = idString;
}
}
Are you certain the BeanObject's hashcode values are unique? That hashcode method seems like it would map a lot of objects to 0 if any of its fields hashed to 0 since it is straight multiplication. I would suggest updating to a more standardized approach for it like the following:
#Override
public int hashCode() {
return Objects.hash(id, name, shortName);
}
Objects.hash is from the java.util package.
If this still doesn't solve the problem, I would double check the hashcode results for each bean object at add time.
I have a code like this:
public interface BatchExecuteHistoryRepository extends JpaRepository<BatchExecuteHistory, Long> {
Page<BatchExecuteHistory> findByBatchExecuteHistoryIdBatchIdOrderByTimeEndAsc(String batchId, Pageable pageable);
}
Here is my database:
Here is what I got on my website:
Anyone know why the query does not work with Order By time_end ASC???
I tried findByBatchExecuteHistoryIdBatchId(String batchId, Pageable pageable) and got the same result
Notice that BatchExecuteHistoryId is a composite id, and batchId is a element of it
Update, here is my BatchExecuteHistory class:
public class BatchExecuteHistory implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private BatchExecuteHistoryId batchExecuteHistoryId;
#NotNull
#Size(max = 100)
#Column(name = "batch_name", length = 100, nullable = false)
private String batchName;
#NotNull
#Column(name = "status", nullable = false)
private Boolean status;
#NotNull
#Column(name = "time_end", nullable = false)
private Instant timeEnd;
#Size(max = 100)
#Column(name = "error_step", length = 100)
private String errorStep;
#Size(max = 100)
#Column(name = "error_content", length = 100)
private String errorContent;
#Column(name = "row_input")
private Long rowInput;
public BatchExecuteHistoryId getBatchExecuteHistoryId() {
return batchExecuteHistoryId;
}
public void setBatchExecuteHistoryId(BatchExecuteHistoryId batchExecuteHistoryId) {
this.batchExecuteHistoryId = batchExecuteHistoryId;
}
public Boolean getStatus() {
return status;
}
public String getBatchName() {
return batchName;
}
public BatchExecuteHistory batchName(String batchName) {
this.batchName = batchName;
return this;
}
public void setBatchName(String batchName) {
this.batchName = batchName;
}
public Boolean isStatus() {
return status;
}
public BatchExecuteHistory status(Boolean status) {
this.status = status;
return this;
}
public void setStatus(Boolean status) {
this.status = status;
}
public Instant getTimeEnd() {
return timeEnd;
}
public BatchExecuteHistory timeEnd(Instant timeEnd) {
this.timeEnd = timeEnd;
return this;
}
public void setTimeEnd(Instant timeEnd) {
this.timeEnd = timeEnd;
}
public String getErrorStep() {
return errorStep;
}
public BatchExecuteHistory errorStep(String errorStep) {
this.errorStep = errorStep;
return this;
}
public void setErrorStep(String errorStep) {
this.errorStep = errorStep;
}
public String getErrorContent() {
return errorContent;
}
public BatchExecuteHistory errorContent(String errorContent) {
this.errorContent = errorContent;
return this;
}
public void setErrorContent(String errorContent) {
this.errorContent = errorContent;
}
public Long getRowInput() {
return rowInput;
}
public BatchExecuteHistory rowInput(Long rowInput) {
this.rowInput = rowInput;
return this;
}
public void setRowInput(Long rowInput) {
this.rowInput = rowInput;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((batchExecuteHistoryId == null) ? 0 : batchExecuteHistoryId.hashCode());
result = prime * result + ((batchName == null) ? 0 : batchName.hashCode());
result = prime * result + ((errorContent == null) ? 0 : errorContent.hashCode());
result = prime * result + ((errorStep == null) ? 0 : errorStep.hashCode());
result = prime * result + ((rowInput == null) ? 0 : rowInput.hashCode());
result = prime * result + ((status == null) ? 0 : status.hashCode());
result = prime * result + ((timeEnd == null) ? 0 : timeEnd.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;
BatchExecuteHistory other = (BatchExecuteHistory) obj;
if (batchExecuteHistoryId == null) {
if (other.batchExecuteHistoryId != null)
return false;
} else if (!batchExecuteHistoryId.equals(other.batchExecuteHistoryId))
return false;
if (batchName == null) {
if (other.batchName != null)
return false;
} else if (!batchName.equals(other.batchName))
return false;
if (errorContent == null) {
if (other.errorContent != null)
return false;
} else if (!errorContent.equals(other.errorContent))
return false;
if (errorStep == null) {
if (other.errorStep != null)
return false;
} else if (!errorStep.equals(other.errorStep))
return false;
if (rowInput == null) {
if (other.rowInput != null)
return false;
} else if (!rowInput.equals(other.rowInput))
return false;
if (status == null) {
if (other.status != null)
return false;
} else if (!status.equals(other.status))
return false;
if (timeEnd == null) {
if (other.timeEnd != null)
return false;
} else if (!timeEnd.equals(other.timeEnd))
return false;
return true;
}
#Override
public String toString() {
return "BatchExecuteHistory [" + batchExecuteHistoryId.toString() + ", batchName=" + batchName + ", status="
+ status + ", timeEnd=" + timeEnd + ", errorStep=" + errorStep + ", errorContent=" + errorContent
+ ", rowInput=" + rowInput + "]";
}
}
You should add a By before OrderBy, so your method should be: findByBatchExecuteHistoryIdBatchIdByOrderByTimeEndAsc
I think you don't miss naming.See Spring document
OrderBy
findByAgeOrderByLastnameDesc
… where x.age = ?1 order by x.lastname desc
It works well in my environment. I am using 2.6.0 version.
I recommand you check jpa version.and I can't see your BatchExecuteHistoryId class.
Anyway Try it for checking it works well in your environment.
Database
CREATE TABLE MEMBER
(
id character varying(10),
batch_id character varying(10),
create_datetime timestamp without time zone NOT NULL,
CONSTRAINT MEMBER_PK
PRIMARY KEY (id,batch_id)
);
INSERT into MEMBER (id,create_datetime,batch_id) VALUES ('USER1','2021/11/20 14:00:00','1');
INSERT into MEMBER (id,create_datetime,batch_id) VALUES ('USER2','2021/11/15 14:00:00','1');
INSERT into MEMBER (id,create_datetime,batch_id) VALUES ('USER3','2021/11/10 14:00:00','1');
Entity
#Entity(name = "Member")
#Table(name = "member")
#ToString
#Data
public class MemberEntity {
#EmbeddedId
private MemberPk batchExecuteHistoryId;
#Column(name = "create_datetime")
private LocalDateTime createDateTime;
}
Pk of Entity
#Embeddable
#ToString
public class MemberPk implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
#Column(name = "batch_id")
private String batchId;
}
Repository
#Repository
public interface MemberRepository extends JpaRepository<MemberEntity, String> {
public List<MemberEntity> findByBatchExecuteHistoryIdBatchIdOrderByCreateDateTimeAsc(String batchId, Pageable pageable);
}
Service
#Service
public class MemberService {
private final MemberRepository memberRepository;
#Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
#PostConstruct
public void findAllMember() {
List<MemberEntity> memberEntitys = memberRepository.findAll();
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER1, batchId=1), createDateTime=2021-11-20T14:00)
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER2, batchId=1), createDateTime=2021-11-15T14:00)
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER3, batchId=1), createDateTime=2021-11-10T14:00)
memberEntitys.forEach(System.out::println);
System.out.println("----------------------------");
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER3, batchId=1), createDateTime=2021-11-10T14:00)
//MemberEntity(batchExecuteHistoryId=MemberPk(id=USER2, batchId=1), createDateTime=2021-11-15T14:00)
List<MemberEntity> memberEntitysWithOrderBy = memberRepository.findByBatchExecuteHistoryIdBatchIdOrderByCreateDateTimeAsc("1",PageRequest.of(0, 2));
memberEntitysWithOrderBy.forEach(System.out::println);
}
}
I'm trying to write some code that determines if a customer has certain feature. I have this method for that:
#Transactional(readOnly = true)
public boolean customerHasFeature(String customerId, String feature) {
Customer customer = customerDAO.findByCid(customerId);
if(customer != null) {
return customer.hasFeatureNamed(feature);
}
return false;
}
The customerDAO method is here
#Transactional(readOnly = true)
public Customer findByCid(String cid) {
List<Customer> customers = findByCriteriaImpl(Restrictions.eq("cid", cid));
if(customers.size() > 0)
return customers.get(0);
return null;
}
In customerHasFeature after I retrieve the customer it doesn't load the features and I get the error
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.socialware.model.Customer.features, no session or session was closed
When debugging findbyCid, I can see the features loaded after the criteria retrieves the customer, but when returned customer gets to customerHasFeature, it has an error.
I tried adding
Hibernate.initialize(customer.getFeatures());
after I call the customerDAO in customerHasFeature method but then I get
org.hibernate.HibernateException: collection is not associated with any session
I'm using hibernate 3,I appreciate any help or guides.
EDIT
Here's the findByCriteriaImpl method.
List<T> findByCriteriaImpl(Criterion... criterion) {
Criteria crit = createCriteria(getPersistentClass());
if (criterion != null) {
for (Criterion c : criterion) {
crit.add(c);
}
}
long startTime = System.currentTimeMillis();
List<T> toReturn = crit.list();
reportQueryTimeForMonitoring(System.currentTimeMillis() - startTime, "findByCriteriaImpl", "for criteria " + crit);
return toReturn;
}
And the Customer class
public class Customer implements Serializable{
private static final long serialVersionUID = -1L;
#Field(index=Index.UN_TOKENIZED)
private long customerId;
private String cid;
//#Field
private String name;
private Set<Feature> features;
private boolean deleted = false;
private String randomKey;
public Customer() {
}
#Override
public String toString() {
return new StringBuilder()
.append("Customer{")
.append(customerId).append(", ")
.append(cid).append(", ")
.append(name).append(", ")
.append(deleted)
.append("}").toString();
}
#Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if(cid == null) {
if(other.cid != null)
return false;
}
else if(!cid.equals(other.cid))
return false;
if(customerId != other.customerId)
return false;
if(name == null) {
if(other.name != null)
return false;
}
else if(!name.equals(other.name))
return false;
return true;
}
public long getCustomerId() {
return customerId;
}
public void setCustomerId(long customerId) {
this.customerId = customerId;
}
public void addFeature(Feature feature) {
if(null == getFeatures()) {
features = new HashSet<Feature>();
}
features.add(feature);
}
public Set<Feature> getFeatures() {
return features;
}
public void setFeatures(Set<Feature> features) {
this.features = features;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public boolean isDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
public String getRandomKey() {
return randomKey;
}
public void setRandomKey(String randomKey) {
this.randomKey = randomKey;
}
public boolean hasFeatureNamed(String name) {
Set<Feature> features = getFeatures();
if (features == null) {
return false;
}
for (Feature feature : features) {
if (feature != null && feature.getName().equals(name)) {
return true;
}
}
return false;
}
public void removeFeature(String name) {
Set<Feature> features = getFeatures();
if (features == null) {
return;
}
for (Iterator<Feature> i = features.iterator(); i.hasNext();) {
Feature feature = i.next();
if (feature.getName().equals(name)) {
i.remove();
}
}
}
}
Looking at your Customer class, I cannot see how did you map the features set, but note that, however you did, the default fetching type is LAZY, meaning that your collection will not be initialized during the read.
Please try the following:
List<T> findByCriteriaImpl(List<String> fetches, Criterion... criterion) {
Criteria crit = createCriteria(getPersistentClass());
if (criterion != null) {
for (Criterion c : criterion) {
crit.add(c);
}
for (String s : fetches) {
crit.setFetchMode(s, FetchMode.JOIN);
}
}
long startTime = System.currentTimeMillis();
List<T> toReturn = crit.list();
reportQueryTimeForMonitoring(System.currentTimeMillis() - startTime, "findByCriteriaImpl", "for criteria " + crit);
return toReturn;
}
And call the findByCriteriaImpl like:
List<Customer> customers = findByCriteriaImpl(Collections.asList("features"), Restrictions.eq("cid", cid));
This way you can tell your method which collections you want to fetch together with your entity.
I am beginner using java and spring jpa (expecially Jhipster). I want to create object in object like this :
But I always get like this :
property buildingsDTO always empty, this is my code, please correct my code in order I get like first picture.
location.java (Domain)
public class Location implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "content_location", nullable = false)
private String content_location;
#OneToMany(mappedBy = "location")
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Building> buildings = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent_location() {
return content_location;
}
public Location content_location(String content_location) {
this.content_location = content_location;
return this;
}
public void setContent_location(String content_location) {
this.content_location = content_location;
}
public Set<Building> getBuildings() {
return buildings;
}
public Location buildings(Set<Building> buildings) {
this.buildings = buildings;
return this;
}
public Location addBuilding(Building building) {
this.buildings.add(building);
building.setLocation(this);
return this;
}
public Location removeBuilding(Building building) {
this.buildings.remove(building);
building.setLocation(null);
return this;
}
public void setBuildings(Set<Building> buildings) {
this.buildings = buildings;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Location location = (Location) o;
if (location.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), location.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "Location{" +
"id=" + getId() +
", content_location='" + getContent_location() + "'" +
"}";
}}
locationDTO.java
public class LocationDTO implements Serializable {
private Long id;
#NotNull
private String content_location;
private Set<BuildingDTO> buildings = new HashSet<>();
public Set<BuildingDTO> getBuildingsDTO() {
return buildings;
}
public void setBuildingsDTO(Set<BuildingDTO> buildings) {
this.buildings = buildings;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent_location() {
return content_location;
}
public void setContent_location(String content_location) {
this.content_location = content_location;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LocationDTO locationDTO = (LocationDTO) o;
if(locationDTO.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), locationDTO.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "LocationDTO{" +
"id=" + getId() +
", content_location='" + getContent_location() + "'" +
"}";
}}
locationMapper.java
public interface LocationMapper extends EntityMapper <LocationDTO, Location> {
#Mapping(target = "buildings", ignore = true)
Location toEntity(LocationDTO locationDTO);
default Location fromId(Long id) {
if (id == null) {
return null;
}
Location location = new Location();
location.setId(id);
return location;
}}
buildingDTO.java
public class BuildingDTO implements Serializable {
private Long id;
#NotNull
private String content_building;
private Long locationId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent_building() {
return content_building;
}
public void setContent_building(String content_building) {
this.content_building = content_building;
}
public Long getLocationId() {
return locationId;
}
public void setLocationId(Long locationId) {
this.locationId = locationId;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
BuildingDTO buildingDTO = (BuildingDTO) o;
if(buildingDTO.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), buildingDTO.getId());
}
#Override
public int hashCode() {
return Objects.hashCode(getId());
}
#Override
public String toString() {
return "BuildingDTO{" +
"id=" + getId() +
", content_building='" + getContent_building() + "'" +
"}";
}}
please anyone help me.
thanks.
By default jHipster will mark any OneToMany entity relationships as #JsonIgnore so that the Set of buildings is not returned in the JSON:
#OneToMany(mappedBy = "location")
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Building> buildings = new HashSet<>();
If you want this to show up in the JSON then you should remove that annotation and also mark it with an eager loading strategy so that the set of buildings are loaded as you expect:
#OneToMany(mappedBy = "location", fetch = FetchType.EAGER)
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Building> buildings = new HashSet<>();
Someone can please suggest me how I can do equals and hashCode methods of these entities?
This is a many-to-many relationship between a Gara (Contest) and Agenzia (Agency):
One contest has many Agency, one Agency can be in more Contest.
I tried some implementations but or I get Stackoverflow error, or,
when I'm updating a Gara (Contest), I can't update the set of Agenzie (Agencies) because i get this error:
org.springframework.dao.DuplicateKeyException: a different object with
the same identifier value was already associated with the session:
[com.myApp.model.GaraAgenzia#com.mmyApp.model.GaraAgenziaId#49f];
nested exception is org.hibernate.NonUniqueObjectException: a
different object with the same identifier value was already associated
with the session:
[com.myApp.model.GaraAgenzia#com.myApp.model.GaraAgenziaId#49f]
when i try to do an update.
thanks
Gare.java:
#Entity
#Table(name = "gare")
public class Gara extends BaseEntity implements Serializable {
private static final long serialVersionUID = 6395640401966812691L;
/*
* inizializzo logger
*/
static Logger logger = LoggerFactory.getLogger(Gara.class);
/*
* molti a molti gara-agenzia
*
* EAGER altrimenti da errore: could not initialize proxy - no Session
*/
#OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.gara", cascade=CascadeType.ALL, orphanRemoval=true)
private Set<GaraAgenzia> garaAgenzie = new HashSet<GaraAgenzia>(0);
/*
* molti a molti gara-servizi
*
* EAGER altrimenti da errore: could not initialize proxy - no Session
*/
#OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.gara", cascade=CascadeType.ALL, orphanRemoval=true)
private Set<GaraServizio> garaServizi = new HashSet<GaraServizio>(0);
/*
*
* colonna TITOLO
*
*/
#NotNull(message = "Il campo TITOLO è obbligatorio")
#NotEmpty(message = "Il campo TITOLO è obbligatorio")
#Size(min = 0, max = 255, message = "Lunghezza massima campo TITOLO: 255 caratteri")
#Column(name = "TITOLO", length = 255)
private String titolo;
/*
*
* colonna OBIETTIVO
*
*/
#NotNull(message = "Il campo OBIETTIVO è obbligatorio")
#Min(value = 1, message = "Il campo OBIETTIVO deve essere maggiore di ZERO")
#Column(name = "OBIETTIVO")
private int obiettivo = 0;
/*
*
* colonna BONUS
*
*/
#NotNull(message = "Il campo BONUS è obbligatorio")
#Min(value = 1, message = "Il campo BONUS deve essere maggiore di UNO")
#Column(name = "BONUS")
private float bonus = 0f;
#Column(name = "data_iniziale", nullable = false)
private Date dataIniziale;
#Column(name = "data_finale", nullable = false)
private Date dataFinale;
public Set<GaraAgenzia> getGaraAgenzie() {
return garaAgenzie;
}
public void setGaraAgenzie(Set<GaraAgenzia> garaAgenzie) {
this.garaAgenzie.clear();
this.garaAgenzie = garaAgenzie;
}
public Set<GaraServizio> getGaraServizi() {
return garaServizi;
}
public void setGaraServizi(Set<GaraServizio> garaServizi) {
this.garaServizi.clear();
this.garaServizi = garaServizi;
}
public void GaraServizio(GaraServizio gara_servizio) {
garaServizi.add(gara_servizio);
gara_servizio.setGara(this);
}
public void removeGaraServizio(GaraServizio gara_servizio) {
garaServizi.remove(gara_servizio);
gara_servizio.setGara(null);
}
public void GaraAgenzia(GaraAgenzia gara_agenzia) {
garaAgenzie.add(gara_agenzia);
gara_agenzia.setGara(this);
}
public void removeGaraAgenzia(GaraAgenzia gara_agenzia) {
garaAgenzie.remove(gara_agenzia);
gara_agenzia.setGara(null);
}
public String getTitolo() {
return titolo;
}
public void setTitolo(String titolo) {
this.titolo = titolo;
}
public int getObiettivo() {
return obiettivo;
}
public void setObiettivo(int obiettivo) {
this.obiettivo = obiettivo;
}
public float getBonus() {
return bonus;
}
public void setBonus(float bonus) {
this.bonus = bonus;
}
public Date getDataIniziale() {
return dataIniziale;
}
public void setDataIniziale(Date dataIniziale) {
this.dataIniziale = dataIniziale;
}
public Date getDataFinale() {
return dataFinale;
}
public void setDataFinale(Date dataFinale) {
this.dataFinale = dataFinale;
}
#Override
public String toString() {
return "Gara [garaAgenzie=" + garaAgenzie + ", garaServizi="
+ garaServizi + ", titolo=" + titolo + ", obiettivo="
+ obiettivo + ", bonus=" + bonus + ", dataIniziale="
+ dataIniziale + ", dataFinale=" + dataFinale + "]";
}
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Float.floatToIntBits(bonus);
result = prime * result
+ ((dataFinale == null) ? 0 : dataFinale.hashCode());
result = prime * result
+ ((dataIniziale == null) ? 0 : dataIniziale.hashCode());
result = prime * result + obiettivo;
result = prime * result + ((titolo == null) ? 0 : titolo.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Gara other = (Gara) obj;
if (Float.floatToIntBits(bonus) != Float.floatToIntBits(other.bonus))
return false;
if (dataFinale == null) {
if (other.dataFinale != null)
return false;
} else if (!dataFinale.equals(other.dataFinale))
return false;
if (dataIniziale == null) {
if (other.dataIniziale != null)
return false;
} else if (!dataIniziale.equals(other.dataIniziale))
return false;
if (obiettivo != other.obiettivo)
return false;
if (titolo == null) {
if (other.titolo != null)
return false;
} else if (!titolo.equals(other.titolo))
return false;
return true;
}
}
GaraAgenzia.java:
#Entity
#Table(name = "gare_agenzie")
#AssociationOverrides({
#AssociationOverride(name = "pk.gara",
joinColumns = #JoinColumn(name = "gara_id")),
#AssociationOverride(name = "pk.agenzia",
joinColumns = #JoinColumn(name = "agenzia_id")) })
public class GaraAgenzia implements Serializable {
private static final long serialVersionUID = 3865586469933888797L;
/*
* inizializzo logger
*/
static Logger logger = LoggerFactory.getLogger(GaraAgenzia.class);
/*
*
* numero contratti:
*
*
*/
private int numeroContratti = 0;
private GaraAgenziaId pk = new GaraAgenziaId();
#EmbeddedId
public GaraAgenziaId getPk() {
return pk;
}
public void setPk(GaraAgenziaId pk) {
this.pk = pk;
}
#Transient
public Gara getGara() {
return getPk().getGara();
}
public void setGara(Gara gara) {
getPk().setGara(gara);
}
#Transient
public Agenzia getAgenzia() {
return getPk().getAgenzia();
}
public void setAgenzia(Agenzia agenzia) {
getPk().setAgenzia(agenzia);
}
#Column(name = "numero_contratti")
public int getNumeroContratti() {
return numeroContratti;
}
public void setNumeroContratti(int numeroContratti) {
this.numeroContratti = numeroContratti;
}
public boolean equals(Object other) {
if (this == other) return true;
if ( !(other instanceof GaraAgenzia) ) return false;
final GaraAgenzia gara_agenzia = (GaraAgenzia) other;
if ( !gara_agenzia.getGara().equals( getGara() ) ) return false;
if ( !gara_agenzia.getAgenzia().equals( getAgenzia() ) ) return false;
return true;
}
public int hashCode() {
int result;
result = getGara().hashCode();
result = 29 * result + getAgenzia().hashCode();
return result;
}
}
GaraAgenziaId.java:
#Embeddable
public class GaraAgenziaId implements Serializable {
private static final long serialVersionUID = 4934033367128755763L;
/*
* inizializzo logger
*/
static Logger logger = LoggerFactory.getLogger(GaraAgenziaId.class);
private Gara gara;
private Agenzia agenzia;
#ManyToOne
public Gara getGara() {
return gara;
}
public void setGara(Gara gara) {
this.gara = gara;
}
#ManyToOne
public Agenzia getAgenzia() {
return agenzia;
}
public void setAgenzia(Agenzia agenzia) {
this.agenzia = agenzia;
}
/*
* override del metodo di uguaglianza
*/
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null)
return false;
if (o instanceof GaraAgenzia) {
final GaraAgenzia other = (GaraAgenzia) o;
return (Objects.equal(getGara().getId(), other.getGara().getId())) && (Objects.equal(getAgenzia().getId(), other.getAgenzia().getId()));
}
return false;
}
/*
* override del metodo creazione hashcode
*/
#Override
public int hashCode() {
return Objects.hashCode(getGara().getId(), getAgenzia().getId());
}
/*
public boolean equals(Object other) {
if (this == other) return true;
if ( !(other instanceof GaraAgenziaId) ) return false;
final GaraAgenziaId gara_agenzia = (GaraAgenziaId) other;
if ( !gara_agenzia.getGara().equals( getGara() ) ) return false;
if ( !gara_agenzia.getAgenzia().equals( getAgenzia() ) ) return false;
return true;
}
public int hashCode() {
int result;
result = getGara().hashCode();
result = 29 * result + getAgenzia().hashCode();
return result;
}
*/
/*
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
GaraAgenziaId other = (GaraAgenziaId) obj;
if (gara == null) {
if (other.gara != null)
return false;
} else if (!gara.equals(other.gara))
return false;
if (agenzia == null) {
if (other.agenzia != null)
return false;
} else if (!agenzia.equals(other.agenzia))
return false;
return true;
}
*/
}
Edit 1:
If i clear the set of Agencies (and Services) before
set again it:
garaToUpdate.getGaraAgenzie().clear();
garaToUpdate.getGaraServizi().clear();
getCurrentSession().flush();
garaToUpdate.setGaraAgenzie(gara.getGaraAgenzie());
garaToUpdate.setGaraServizi(gara.getGaraServizi());
getCurrentSession().update(garaToUpdate);
i get this error:
A collection with cascade="all-delete-orphan" was no longer
referenced by the owning entity instance:
Edit 2:
As suggested by #JamesB, i added the toString method to GaraAgenzia and GaraAgenziaId. Here the result BEFORE update the Gara record:
this is the record taken from db just before update it
INFO : com.machinet.model.GaraAgenziaId - garaToUpdate.GaraAgenzie
(before update): [GaraAgenzia [numeroContratti=0, pk=GaraAgenziaId
[Gara=Gara [titolo=gara title, obiettivo=999, bonus=100.00,
dataIniziale=2014-07-31, dataFinale=2014-07-31], agenzia=Agenzia(id=1,
nome='Agency 1 ltd', ragione sociale=Agency 1 ltd srl)]]]
this is the edited record that will be set in db:
INFO : com.machinet.model.GaraAgenziaId - editedGara.GaraAgenzie
(before update): [GaraAgenzia [numeroContratti=0, pk=GaraAgenziaId
[Gara=Gara [titolo=gara title, obiettivo=999, bonus=100.00,
dataIniziale=2014-07-31, dataFinale=2014-07-31], agenzia=Agenzia(id=1,
nome='Agency 1 ltd', ragione sociale=Agency 1 ltd srl]]]
These seem to work well. I post hoping someone will find it useful:
GaraAgenzia class:
public boolean equals(Object o) {
if (this== o) return true;
if (o ==null|| getClass() != o.getClass()) return false;
GaraAgenzia that = (GaraAgenzia) o;
if (getPk() !=null?!getPk().equals(that.getPk()) : that.getPk() !=null) return false;
return true;
}
public int hashCode() {
return (getPk() !=null? getPk().hashCode() : 0);
}
GaraAgenziaId class:
public boolean equals(Object o) {
if (this== o) return true;
if (o ==null|| getClass() != o.getClass()) return false;
GaraAgenziaId that = (GaraAgenziaId) o;
if (gara !=null?!gara.equals(that.gara) : that.gara !=null) return false;
if (agenzia !=null?!agenzia.equals(that.agenzia) : that.agenzia !=null)
return false;
return true;
}
public int hashCode() {
int result;
result = (agenzia !=null? agenzia.hashCode() : 0);
result =31* result + (gara !=null? gara.hashCode() : 0);
return result;
}
It is not an exactly answer, but may help someone in a similar problem. I made a abstract class that is extended by all the entities. This way I don't need to implement these methods in all entities.
public abstract class GenericEntity implements Serializable{
protected static final long serialVersionUID = 1L;
abstract public Serializable getId();
#Override
public int hashCode()
{
return (getId() == null) ? System.identityHashCode(this) : getId().hashCode();
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (this.getClass() != obj.getClass())
return false;
if (org.hibernate.Hibernate.getClass(this) != org.hibernate.Hibernate.getClass(obj))
return false;
GenericEntity other = (GenericEntity) obj;
if (getId() == null || other.getId() == null)
return false;
return getId().equals(other.getId());
}
}
I think in your case you could put it in your BaseEntity.