I created some model, for equipment, but I am not sure if I did correct mapping, also when I want to get rid of eager loading I got error:
"Type definition error: [simple type, class
org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]; nested
exception is
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No
serializer found for class
org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no
properties discovered to create BeanSerializer (to avoid exception,
disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference
chain:
java.util.ArrayList[0]-com.winterrent.winterrent.entity.ItemProperty[\"item\"]-com.winterrent.winterrent.entity.Item$HibernateProxy$RO0mkQSh[\"hibernateLazyInitializer\"])",
but if I change the fetch type to eager everything works fine.
My reverse engineering schema:
Then my entities:
import javax.persistence.*;
import java.util.Objects;
#Entity
#Table(name = "item")
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Enumerated(EnumType.STRING)
#Column(name = "type")
private ItemType itemType;
public Item() {
}
public Item(ItemType itemType) {
this.itemType = itemType;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public ItemType getItemType() {
return itemType;
}
public void setItemType(ItemType itemType) {
this.itemType = itemType;
}
#Override
public String toString() {
return "Item{" +
"id=" + id +
", itemType=" + itemType +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
return id == item.id &&
Objects.equals(itemType, item.itemType);
}
#Override
public int hashCode() {
return Objects.hash(id, itemType);
}
}
2)
public enum ItemType {
SKI, BOARD
}
3)
import javax.persistence.*;
import java.util.Objects;
#Entity
#Table(name = "item_property_definition")
public class ItemPropertyDefinition {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "property_name")
private String propertyName;
#Column(name = "type")
#Enumerated(EnumType.STRING)
private ItemType itemType;
public ItemPropertyDefinition() {
}
public ItemPropertyDefinition(String propertyName, ItemType itemType) {
this.propertyName = propertyName;
this.itemType = itemType;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public ItemType getItemType() {
return itemType;
}
public void setItemType(ItemType itemType) {
this.itemType = itemType;
}
#Override
public String toString() {
return "ItemPropertyDefinition{" +
"id=" + id +
", propertyName='" + propertyName + '\'' +
", itemType=" + itemType +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemPropertyDefinition that = (ItemPropertyDefinition) o;
return id == that.id &&
Objects.equals(propertyName, that.propertyName) &&
Objects.equals(itemType, that.itemType);
}
#Override
public int hashCode() {
return Objects.hash(id, propertyName, itemType);
}
}
And finally mapping:
import javax.persistence.*;
import java.util.Objects;
#Entity
#Table(name = "item_properties")
public class ItemProperty {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "item_id")
private Item item;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "item_property_definition_id")
private ItemPropertyDefinition itemPropertyDefinition;
#Column(name = "value")
private String value;
public ItemProperty(){}
public ItemProperty(Item item, ItemPropertyDefinition itemPropertyDefinition, String value) {
this.item = item;
this.itemPropertyDefinition = itemPropertyDefinition;
this.value = value;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public ItemPropertyDefinition getItemPropertyDefinition() {
return itemPropertyDefinition;
}
public void setItemPropertyDefinition(ItemPropertyDefinition itemPropertyDefinition) {
this.itemPropertyDefinition = itemPropertyDefinition;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String toString() {
return "ItemProperty{" +
"id=" + id +
", item=" + item +
", itemPropertyDefinition=" + itemPropertyDefinition +
", value='" + value + '\'' +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemProperty that = (ItemProperty) o;
return id == that.id &&
Objects.equals(item, that.item) &&
Objects.equals(itemPropertyDefinition, that.itemPropertyDefinition) &&
Objects.equals(value, that.value);
}
#Override
public int hashCode() {
return Objects.hash(id, item, itemPropertyDefinition, value);
}
}
Thank you for the hints. It's my first playing around with backend.
The problem is that you are overriding toString(), equals() and hashCode() methods using entities. Everything, that is used inside those functions need to be basic entities, that are loaded together with parent entity. That is why there was no exception was thrown, when loaded eagerly.
In general I wouldn't recommend using child entities to determine equality and so on as, for example, this requires them to be loaded eagerly, which is not good for performance. I would leave them lazily loaded and rewrite overridden methods for performance sake, but if you need them used in those methods, you need to load them eagerly.
Vlad Mihalcea wrote a good read about implementing toString(), equals and hashCode().
Related
I am creating a REST API using Spring Boot and for my update method I try to map a DTO Object to a domain one:
public ItemDTO updateItem(Long departmentId, Long itemId, ItemDTO itemDTO) throws ApiException {
Department department = departmentRepository.findById(departmentId).orElseThrow(
() -> new ApiException("Department with this id does not exist ",
HttpStatus.NOT_FOUND));
Item foundItem = validateItem(itemId);
Item convertedItem = mapper.convertToType(itemDTO, Item.class);
if (convertedItem.getStock() < 0) {
throw new ApiException("Stock must be a positive value", HttpStatus.BAD_REQUEST);
}
if (convertedItem.getStockThreshold() < 0) {
throw new ApiException("Stock threshold must be a positive value", HttpStatus.BAD_REQUEST);
}
itemDTO.setId(itemId);
itemDTO.setDepartment(mapper.convertToType(department, DepartmentDTO.class));
foundItem = mapper.convertToType(itemDTO, Item.class);
itemRepository.save(foundItem);
// ItemDTO returnItem = mapper.convertToType(convertedItem, ItemDTO.class);
logger.info("Updated item");
return itemDTO;
}
And this is my model mapper
#Component
public class Mapper {
private final ModelMapper modelMapper;
private final Logger logger = LoggerFactory.getLogger(ModelMapper.class);
public Mapper(ModelMapper modelMapper) {
this.modelMapper = modelMapper;
}
public <T> T convertToType(Object source, Class<T> resultClass) {
logger.debug("converted object from " + source.getClass().getSimpleName() + " to " + resultClass.getSimpleName());
return modelMapper.map(source, resultClass);
}
}
At this line foundItem = mapper.convertToType(itemDTO, Item.class); it's the problem, before this conversion my foundItem would have a department, after conversion, the department field is null.
Here are my domain and DTO classes
#NoArgsConstructor
#Getter
#Setter
public class DepartmentDTO {
private Long id;
private String description;
private List<Item> items;
public DepartmentDTO(long id, String description) {
this.id = id;
this.description = description;
}
#Override
public String toString() {
return "DepartmentDTO{" +
"id=" + id +
", description='" + description + '\'' +
", items=" + items +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DepartmentDTO that = (DepartmentDTO) o;
return Objects.equals(id, that.id) && Objects.equals(description, that.description) && Objects.equals(items, that.items);
}
// #Override
// public int hashCode() {
// return Objects.hash(id, description, items);
// }
}
#NoArgsConstructor
#Entity
#Getter
#Setter
#Table(name = "DEPARTMENTS")
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
#OneToMany(mappedBy = "department", fetch = FetchType.EAGER,
cascade = CascadeType.ALL)
private List<Item> items;
public Department(Long id, String description) {
this.id = id;
this.description = description;
}
#Override
public String toString() {
return "Department{" +
"id=" + id +
", description='" + description + '\'' +
", items=" + items +
'}';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Department)) return false;
Department that = (Department) o;
return id.equals(that.id) && Objects.equals(description, that.description) && Objects.equals(items, that.items);
}
#Override
public int hashCode() {
return Objects.hash(id, description, items);
}
}
#AllArgsConstructor
#NoArgsConstructor
#Setter
public class ItemDTO {
private Long id;
private String description;
private String price;
private int stock;
private int stockThreshold;
private DepartmentDTO department;
public Long getId() {
return id;
}
public String getDescription() {
return description;
}
public String getPrice() {
return price;
}
public int getStock() {
return stock;
}
public int getStockThreshold() {
return stockThreshold;
}
public Long getDepartment() {
return department.getId();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemDTO itemDTO = (ItemDTO) o;
return stock == itemDTO.stock && stockThreshold == itemDTO.stockThreshold &&
id.equals(itemDTO.id) && description.equals(itemDTO.description) &&
price.equals(itemDTO.price) && department.equals(itemDTO.department);
}
#Override
public int hashCode() {
return Objects.hash(id, description, price, stock);
}
}
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
#Entity
#Table(name = "ITEMS")
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Long id;
private String description;
private String price;
private int stock;
private int stockThreshold = 5;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "department_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
#JsonIgnore
private Department department;
#Override
public String toString() {
return "Item{" +
"id=" + id +
", description='" + description + '\'' +
", price='" + price + '\'' +
", stock=" + stock +
", department=" + department +
'}';
}
}
when I use #OrderColumn annotation, Hibernate returns collection with 42075 [Null] records, but without #OrderColumn everything works perfectly why? I want to use field "OrderNumber" to have always ordered entity by this field. The type of this "OrderNumber" on PostgreSQL side is "serial" with auto increasing count.
DocTestEntity:
#Entity
#Table(name = "`Document`")
public class DocTestEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "`Document_ID`")
private Integer id;
#ManyToMany
#JoinTable(name = "`DocumentEmployee`",
joinColumns = #JoinColumn(name = "`Document_ID`"),
inverseJoinColumns = #JoinColumn(name = "`Employee_ID`"))
#OrderColumn(name ="`OrderNumber`", updatable = false, insertable = false)
private List<EmployeeTestEntity> employeeEntityList;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<EmployeeTestEntity> getEmployeeEntityList() {
return employeeEntityList;
}
public void setEmployeeEntityList(List<EmployeeTestEntity> employeeEntityList) {
this.employeeEntityList = employeeEntityList;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DocTestEntity docEntity = (DocTestEntity) o;
return Objects.equals(id, docEntity.id);
}
#Override
public int hashCode() {
return Objects.hash(id);
}
#Override
public String toString() {
return "DocTestEntity{" +
"id=" + id +
'}';
}
}
EmployeeTestEntity:
#Entity
#Table(name = "`Employee`")
public class EmployeeTestEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "`Employee_ID`")
private Integer id;
#Column(name = "`Employee_name`")
private String name;
#Column(name = "`Employee_surname`")
private String surname;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String employeeName) {
this.name = employeeName;
}
public String getSurname() {
return surname;
}
public void setSurname(String employeeSurname) {
this.surname = employeeSurname;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EmployeeTestEntity that = (EmployeeTestEntity) o;
return Objects.equals(id, that.id);
}
#Override
public int hashCode() {
return Objects.hash(id);
}
#Override
public String toString() {
return "EmployeeTestEntity{" +
"id=" + id +
'}';
}
}
And Test DAO:
#Stateless
public class DocTestDAO {
#PersistenceContext
private EntityManager em;
public DocTestEntity selectDocumentByID(Integer id) {
var result = em.createQuery("SELECT DISTINCT a from DocTestEntity a " +
" WHERE a.id = :id ", DocTestEntity.class)
.setParameter("id", id)
.getResultStream()
.map(Optional::ofNullable)
.findFirst()
.flatMap(Function.identity())
.orElse(null);
System.out.println("List records count is: " + result.getEmployeeEntityList().size());
return result;
}
}
You don't need the OrderNumber column to be autoincremented, the hibernate can manage the order column itself depending on the order of the items in the collection employeeEntityList.
You should make the OrderNumber to be insertable and updatable (true by default):
#OrderColumn(name = "OrderNumber")
I would recommend cleaning up the code, removing these apostrophes from the column names
"`DocumentEmployee`" should be "DocumentEmployee". You mentioned that everything could work without #OrderColumn, so I suppose apostrophes don't affect the functionality but look weird.
Please let me know if this still doesn't work after mentioned updates.
I want to manage Persons, Teams and their Membership with Spring Data JPA.
The following test (whenAddingANewTeamTroughPerson)
passes when I use entityManager.persist(alex);
throws an exception if I use personRepository.save(alex);
Why? In the latter case I get the following exception:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: hello.data.model.Person; nested exception is java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: hello.data.model.Person
It behaves as CASCADE is not set properely. But it must be correct, since it works with the entityManager.
PersonRepositoryTest:
#RunWith(SpringRunner.class)
#DataJpaTest
public class PersonRepositoryTest {
#Autowired
private TestEntityManager entityManager;
#Autowired
private PersonRepository personRepository;
#Autowired
private TeamRepository teamRepository;
#Test
public void whenFindOne_thenReturnPerson() {
// given
Person alex = new Person("alex");
entityManager.persist(alex);
entityManager.flush();
// when
Person found = personRepository.findOne(alex.getId());
// then
assertThat(found.getName(), equalToIgnoringWhiteSpace(alex.getName()));
}
#Test
public void whenAddingANewTeamTroughPerson_thenNoException() {
// given
Person alex = new Person("alex");
Team t = new Team("team");
alex.addTeam(t, "integrationTest", new Date());
personRepository.save(alex);
//entityManager.persist(alex);
// when
Person found = personRepository.findOne(alex.getId());
// then
assertThat(found.getTeams().size(), is(1));
}
}
PersonRepository:
public interface PersonRepository extends CrudRepository<Person, Integer> {}
Person:
#Entity
public class Person {
private static final Logger LOG = LoggerFactory.getLogger(Person.class);
private final IntegerProperty id = new SimpleIntegerProperty(this, "id");
private final StringProperty name = new SimpleStringProperty(this, "name");
private Set<PersonTeam> personTeams = new LinkedHashSet<>();
private ListProperty<Team> teams = new SimpleListProperty<>(this, "teams", FXCollections.observableArrayList());
public Person(String s) {
this.name.set(s);
}
public Person() {}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer getId() {
return id.get();
}
public void setId(Integer id) {
this.id.set(id);
}
public IntegerProperty idProperty() {
return id;
}
#Basic
#Column(name = "name")
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.person", cascade=CascadeType.ALL, orphanRemoval = true)
public Set<PersonTeam> getPersonTeams() {
return personTeams;
}
public void setPersonTeams(Set<PersonTeam> personTeams) {
this.personTeams = personTeams;
teams.setAll(personTeams.stream().map(PersonTeam::getTeam).collect(Collectors.toList()));
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (getId() != null ? !getId().equals(person.getId()) : person.getId() != null) return false;
if (getName() != null ? !getName().equals(person.getName()) : person.getName() != null) return false;
return true;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
return result;
}
/**
* Returns an Observable List that must remain unchanged.
* Unfortunately there is no RO Observable List Interface to refer to.
*/
#Transient
public ObservableList<Team> getTeams() {
return teams.get();
}
#Transient
public ReadOnlyListProperty<Team> teamsProperty() {
return teams;
}
public void addTeam(Team team, String createdBy, Date createdDate) {
final PersonTeam personTeam = new PersonTeam(this, team);
personTeam.setCreatedBy(createdBy);
personTeam.setCreatedDate(createdDate);
if( !personTeams.add(personTeam) ) {
LOG.error("Failed to add personTeam " + personTeam + " to collection personTeams " + personTeams);
}
if( !team.getPersonTeams().add( personTeam ) ) {
LOG.error("Failed to add personTeam " + personTeam + " to collection team.getPersonTeams " + team.getPersonTeams());
}
teams.setAll(personTeams.stream().map(PersonTeam::getTeam).collect(Collectors.toList()));
}
public void removeTeam(Team team) {
PersonTeam personTeam = new PersonTeam( this, team );
team.getPersonTeams().remove( personTeam );
personTeams.removeIf( pt -> pt.getTeam() == team );
personTeam.setPerson( null );
personTeam.setTeam( null );
teams.setAll(personTeams.stream().map(PersonTeam::getTeam).collect(Collectors.toList()));
}
/*
The method is not intended to be used in the GUI.
Use the {#link GUIRepresentable} interface instead.
*/
#Override
public String toString() {
return name.getValue();
}
}
PersonTeam:
#Entity
#Table(name = "person_team")
#AssociationOverrides({
#AssociationOverride(name = "pk.person",
joinColumns = #JoinColumn(name = "PERSON_ID")),
#AssociationOverride(name = "pk.team",
joinColumns = #JoinColumn(name = "TEAM_ID")) })
public class PersonTeam implements java.io.Serializable {
private PersonTeamPk pk = new PersonTeamPk();
private Date createdDate;
private String createdBy;
public PersonTeam() {
}
public PersonTeam(Person person, Team team) {
this.pk.setPerson(person);
this.pk.setTeam(team);
}
#EmbeddedId
public PersonTeamPk getPk() {
return pk;
}
public void setPk(PersonTeamPk pk) {
this.pk = pk;
}
#Transient
public Person getPerson() {
return getPk().getPerson();
}
public void setPerson(Person person) {
getPk().setPerson(person);
}
#Transient
public Team getTeam() {
return getPk().getTeam();
}
public void setTeam(Team team) {
getPk().setTeam(team);
}
#Temporal(TemporalType.DATE)
#Column(name = "CREATED_DATE", nullable = false, length = 10)
public Date getCreatedDate() {
return this.createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
#Column(name = "CREATED_BY", nullable = false, length = 10)
public String getCreatedBy() {
return this.createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
PersonTeam that = (PersonTeam) o;
if (getPk() != null ? !getPk().equals(that.getPk())
: that.getPk() != null)
return false;
return true;
}
public int hashCode() {
return (getPk() != null ? getPk().hashCode() : 0);
}
}
PersonTeamPk:
#Embeddable
public class PersonTeamPk implements java.io.Serializable {
private Person person;
private Team team;
#ManyToOne(cascade = CascadeType.ALL)
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
#ManyToOne(cascade = CascadeType.ALL)
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PersonTeamPk that = (PersonTeamPk) o;
if (person != null ? !person.equals(that.person) : that.person != null) return false;
if (team != null ? !team.equals(that.team) : that.team != null)
return false;
return true;
}
public int hashCode() {
int result;
result = (person != null ? person.hashCode() : 0);
result = 31 * result + (team != null ? team.hashCode() : 0);
return result;
}
}
Team:
#Entity
public class Team implements Serializable, Comparable<Team> {
private final IntegerProperty id = new SimpleIntegerProperty(this, "id");
private final StringProperty name = new SimpleStringProperty(this, "name");
private Set<PersonTeam> personTeams = new LinkedHashSet<>();
public Team(String s) {
this.name.set(s);
}
public Team() {}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer getId() {
return id.get();
}
public void setId(Integer id) {
this.id.set(id);
}
public IntegerProperty idProperty() {
return id;
}
#Basic
#Column(name = "name")
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.team", orphanRemoval = true, cascade = CascadeType.ALL)
public Set<PersonTeam> getPersonTeams() {
return personTeams;
}
public void setPersonTeams(Set<PersonTeam> personTeams) {
this.personTeams = personTeams;
}
public static Callback<Team, Observable[]> extractor() {
return (Team p) -> new Observable[]{p.nameProperty()};
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Team team = (Team) o;
if (getId() != null ? !getId().equals(team.getId()) : team.getId() != null) return false;
if (getName() != null ? !getName().equals(team.getName()) : team.getName() != null) return false;
return true;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
return result;
}
#Override
public String toString() {
return name.getValue();
}
#Override
public int compareTo(Team o) {
return Integer.compare(getId(), o.getId());
}
}
I have an EJB application in where I am using Entity beans for database. I have to Entity beans having unidirectional one to one relation, JobPositionEntity and CandidateEntity.
Here is CandidateEntity
#Entity
public class CandidateEntity extends BaseEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Long meritNumber;
private String seatNumber;
private String candidateName;
private String gender;
public Long getMeritNumber() {
return meritNumber;
}
public void setMeritNumber(Long meritNumber) {
this.meritNumber = meritNumber;
}
public String getSeatNumber() {
return seatNumber;
}
public void setSeatNumber(String seatNumber) {
this.seatNumber = seatNumber;
}
public String getCandidateName() {
return candidateName;
}
public void setCandidateName(String candidateName) {
this.candidateName = candidateName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
#Override
public Long getId() {
return id;
}
#Override
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 CandidateEntity)) {
return false;
}
CandidateEntity other = (CandidateEntity) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.nisheeth.config.ejb.entity.CandidateEntity[ id=" + id + " ]";
}
}
Here is JobPositionEntity
#Entity
public class JobPositionEntity extends BaseEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#OneToOne(fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.ALL)
private CandidateEntity candidate;
#ManyToOne(fetch = FetchType.EAGER)
private SeasonEntity season;
public SeasonEntity getSeason() {
return season;
}
public void setSeason(SeasonEntity season) {
this.season = season;
}
public CandidateEntity getCandidate() {
return candidate;
}
public void setCandidate(CandidateEntity candidate) {
this.candidate = candidate;
}
#Override
public Long getId() {
return id;
}
#Override
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 JobPositionEntity)) {
return false;
}
JobPositionEntity other = (JobPositionEntity) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "com.nisheeth.config.ejb.entity.JobPositionEntity[ id=" + id + " ]";
}
}
I want to select candidates which are not in JobPositionEntity. I have this query which did not work for me:
select ce.candidateName, ce.id from JobPositionEntity jp left join jp.candidate ce where ce <> null
Can anyone help write this query? Thanks in advance.
you can use a SubQuery
select c from Candidate c where c.id not in
(select jp.candidate.id from JobPositionEntity jp)
for more information:
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html#queryhql-subqueries
I'm trying to map a bidirectional ManyToMany relationship between the class Problem and the class Domain. Therefore the persistency unit creates a join table in the database, but it seems no entry pops up in the database.
Here's some code:
The class Problem
package domain;
import java.io.Serializable;
import java.util.List;
import javax.persistence.*;
import static javax.persistence.GenerationType.SEQUENCE;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#XmlRootElement
public class Problem implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private User user;
private String description;
private int maxprice;
private int priority;
private Solution solution;
private Location location;
private List<Domain> domains;
#Id
//#GeneratedValue(strategy = GenerationType.AUTO)
#SequenceGenerator(name="User_Seq", allocationSize=25)
#GeneratedValue(strategy=SEQUENCE, generator="Problem_Seq")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#ManyToOne
//#JoinColumn(name="user_id")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getMaxPrice() {
return maxprice;
}
public void setMaxPrice(int maxprice) {
this.maxprice = maxprice;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="solution_id")
public Solution getSolution() {
return solution;
}
public void setSolution(Solution solution) {
this.solution = solution;
}
#ManyToOne
#JoinColumn(name="location_id")
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
#ManyToMany
#JoinTable(name="problem_domain",
joinColumns={#JoinColumn(name="problem_id", referencedColumnName="ID")},
inverseJoinColumns={#JoinColumn(name="domain_id", referencedColumnName="ID")})
public List<Domain> getDomains() {
return domains;
}
public void setDomains(List<Domain> domains) {
this.domains = domains;
}
public void addDomain(Domain domain){
//this.domains.add(domain); //Throws NullpointerException om een of andere reden.
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 Problem)) {
return false;
}
Problem other = (Problem) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "domain.Problem[ id=" + id + " ]";
}
}
The class Domain
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package domain;
import java.io.Serializable;
import java.util.List;
import javax.persistence.*;
import static javax.persistence.GenerationType.SEQUENCE;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#XmlRootElement
public class Domain implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private List<Problem> problems;
private List<Domain> subDomains;
private Domain superDomain;
#Id
#SequenceGenerator(name="Dom_Seq", allocationSize=25)
#GeneratedValue(strategy=SEQUENCE, generator="Dom_Seq")
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;
}
#ManyToMany(mappedBy = "domains")
public List<Problem> getProblems() {
return problems;
}
public void setProblems(List<Problem> problems) {
this.problems = problems;
}
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="superdomain_id")
public List<Domain> getSubDomains() {
return subDomains;
}
public void setSubDomains(List<Domain> subDomains) {
this.subDomains = subDomains;
}
public Domain getSuperDomain() {
return superDomain;
}
public void setSuperDomain(Domain superDomain) {
this.superDomain = superDomain;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 Domain)) {
return false;
}
Domain other = (Domain) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "domain.Domain[ id=" + id + " ]";
}
}
the code where we add a problem and a domain to the database
Problem problem = new Problem();
Domain domain = new Domain();
domain.setName(domainString);
domainFacade.create(domain);
problemFacade.create(problem);
problem.addDomain(domain);
problemFacade.edit(problem);
and a little visual explanation of the DB
Do you try to save List of domain to problem?
Example of code:
Problem problem = new Problem();
Domain domain = new Domain();
domain.setName(domainString);
domainFacade.create(domain);
List<Domain> domains = new ArrayList<Domain>();
domains.add(domain);
problem.setDomains(domains);
problemFacade.create(problem);
As #Neil Stockton and others said, the answer to my problem was that I had to have an addMethod that simply added the object to the list.