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
Related
I'm doing a simple exercise to learn JPA.
When I try to delete an entity of type User, which has a Collection of the other entity Score (annotated with #OneToMany) I get this error:
java.sql.SQLIntegrityConstraintViolationException: Column 'user' cannot be null
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 20 more
These are my classes:
User.java
#Entity
#Table(name = "user")
public class User
{
#Id
private Integer id;
#NotNull
#Size(max = 20)
private String name;
#OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL,orphanRemoval = true)
#JoinColumn(name = "user")
private Collection<Score> scores;
public User() {
}
public User(Integer id, String name, Collection<Score> scores) {
this.id = id;
this.name = name;
this.scores = scores;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection<Score> getScores() {
return scores;
}
public void setScores(Collection<Score> scores) {
this.scores = scores;
}
}
Score.java
#Entity
#Table(name = "score")
public class Score
{
#EmbeddedId
private ScoreId id;
#NotNull
private Integer points;
public Score() {
}
public Score(ScoreId id, Integer points) {
this.id = id;
this.points = points;
}
public ScoreId getId() {
return id;
}
public void setId(ScoreId id) {
this.id = id;
}
public Integer getPoints() {
return points;
}
public void setPoints(Integer points) {
this.points = points;
}
#Override
public boolean equals(Object obj) {
if (obj!=null && getClass()==obj.getClass())
{
Score other = (Score) obj;
return Objects.equals(id, other.id) && Objects.equals(points,other.points);
}
return false;
}
#Override
public int hashCode() {
return id!=null ? points!=null ? id.hashCode()+points.hashCode() : 0 : 0;
}
#Override
public String toString() {
return getClass().getName() + "[id =" + id + ",points = " + points;
}
}
ScoreId.java
#Embeddable
public class ScoreId implements Serializable
{
private Integer user;
#Enumerated(EnumType.STRING)
private Game game;
public ScoreId() {
}
public ScoreId(Integer user, Game game) {
this.user = user;
this.game = game;
}
public Integer getUser() {
return user;
}
public void setUser(Integer user) {
this.user = user;
}
public Game getGame() {
return game;
}
public void setGame(Game game) {
this.game = game;
}
public enum Game
{
HANGMAN,
TRIS
}
#Override
public boolean equals(Object obj) {
if (obj!=null && getClass()==obj.getClass())
{
ScoreId other = (ScoreId) obj;
return Objects.equals(user,other.user) && game==other.game;
}
return false;
}
#Override
public int hashCode()
{
return user!=null ? game!=null ? user.hashCode()+game.hashCode() : 0 : 0;
}
#Override
public String toString() {
return getClass().getName() + "[user = " + user + ",game = " + game + "]";
}
}
Main.java
public class Main {
public static void main(String[] args) {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("UserJPA");
EntityManager em = factory.createEntityManager();
EntityTransaction et = em.getTransaction();
User demetrio = em.createQuery("SELECT u FROM User u WHERE u.name = 'Demetrio'",User.class).getSingleResult();
et.begin();
em.remove(demetrio);
et.commit();
em.close();
factory.close();
}
}
This is the script to generate db:
CREATE TABLE `user`
(
id INT PRIMARY KEY,
`name` VARCHAR(20) UNIQUE NOT NULL
);
CREATE TABLE score
(
`user` INT,
game ENUM("HANGMAN","TRIS"),
points INT UNSIGNED NOT NULL,
PRIMARY KEY(`user`,game),
FOREIGN KEY (`user`) REFERENCES `user`(id)
ON UPDATE CASCADE
ON DELETE CASCADE
)
I'm using Hibernate as JPA implementation.
I searched for a solution but I did not find anything.
Maybe I'm doing something wrong.
Can you help me?
The implementation I see is absolutly correct, allthou it always can be improoved. The db-design is good. The exception you post can simply not exist but it does. The Database must have a problem. Thats why I asked to post the DDL of the table. I trust in your DDL you posted what makes me think: You did everything right.
What I do is I could only guess.
The table's engine is InnoDB but what is the status of the InnoDB-engine? Is it working? Is it active? Use SHOW ENGINE INNODB STATUS to see the status of InnoDB.
I solved by replacing Integer user of ScoreId with User user with a #ManyToOne annotation.
These are my classes:
User.java
#Entity
#Table(name = "user")
public class User
{
#Id
private Integer id;
#NotNull
#Size(max = 20)
private String name;
#OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL,orphanRemoval = true,mappedBy = "id.user")
private Collection<Score> scores;
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection<Score> getScores() {
return scores;
}
public void setScores(Collection<Score> scores) {
this.scores = scores;
}
#Override
public boolean equals(Object obj) {
if (obj!=null && getClass()==obj.getClass())
{
User other = (User) obj;
return Objects.equals(id, other.id) && Objects.equals(name, other.name);
}
return false;
}
#Override
public String toString() {
return getClass().getName() + "[id = " + id + ",name = " + name + "]";
}
#Override
public int hashCode() {
return id!=null ? name!=null ? id.hashCode() + name.hashCode() : 0 : 0;
}
}
Score.java
#Entity
#Table(name = "score")
public class Score
{
#EmbeddedId
private ScoreId id;
#NotNull
private Integer points;
public Score() {
}
public Score(ScoreId id, Integer points) {
this.id = id;
this.points = points;
}
#Override
public boolean equals(Object obj) {
if (obj!=null && getClass()==obj.getClass())
{
Score other = (Score) obj;
return Objects.equals(id,other.id) && Objects.equals(points,other.points);
}
return false;
}
#Override
public int hashCode() {
return id!=null ? points!=null ? id.hashCode()+points.hashCode() : 0 : 0;
}
#Override
public String toString() {
return getClass().getName() + "[id =" + id + ",points = " + points + "]";
}
}
ScoreId.java
#Embeddable
public class ScoreId implements Serializable
{
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="user",referencedColumnName = "id")
private User user;
#Enumerated(EnumType.STRING)
private Game game;
public ScoreId() {
}
public ScoreId(User user, Game game) {
this.user = user;
this.game = game;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Game getGame() {
return game;
}
public void setGame(Game game) {
this.game = game;
}
public enum Game
{
HANGMAN,
TRIS
}
#Override
public boolean equals(Object obj) {
if (obj!=null && getClass()==obj.getClass())
{
ScoreId other = (ScoreId) obj;
return Objects.equals(user,other.user) && game==other.game;
}
return false;
}
#Override
public int hashCode()
{
return user!=null ? game!=null ? user.hashCode()+game.hashCode() : 0 : 0;
}
#Override
public String toString() {
return getClass().getName() + "[user = " + user + ",game = " + game + "]";
}
}
Database schema is the same.
In my case there was an Envers used, and on deleteAll() or delete() it tried to insert a record with type 2 (deleted) into corresponding _aud table.
However, when it does so, all the fields of the record appear to be NULL, but in the _aud table one of the columns was marked as "NON-NULL".
Removing the "NON-NULL" from those column in _aud table fixed the issue.
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());
}
}
There are the entities Cookbook, Recipe. It's a ManyToMany relation: a cookbook can have multiple recipes and a recipe can be assigned to multiple cookbooks. So I added the entity CookbookRecipe and connected the entities as OneToMany.
Where to put a method to add/remove the relation between Cookbook and Recipe - does this method has to add a new CookbookRecipe and add this CookbookRecipe to Cookbook and Recipe?
In my understanding I would expect a
public void addRecipe(Recipe recipe) {
CookbookRecipe relation = new CookbookRecipe();
relation.setCookbook(this);
relation.setRecipe(recipe);
this.cookbookRecipes.add( relation );
}
Is this the right direction?
Would I add this method to the Cookbook DAO or Recipe DAO or put this into a service?
#Entity
public class Cookbook {
private Integer id;
private String title;
private Collection<CookbookRecipe> cookbookRecipes;
private Collection<CookbookSortlevel> cookbookSortlevels;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Basic
#Column(name = "title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Cookbook cookbook = (Cookbook) o;
if (id != null ? !id.equals(cookbook.id) : cookbook.id != null) return false;
if (title != null ? !title.equals(cookbook.title) : cookbook.title != null) return false;
return true;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}
#OneToMany(mappedBy = "cookbook", fetch = FetchType.EAGER)
public Collection<CookbookRecipe> getCookbookRecipes() {
return cookbookRecipes;
}
public void setCookbookRecipes(Collection<CookbookRecipe> cookbookRecipes) {
this.cookbookRecipes = cookbookRecipes;
}
#OneToMany(mappedBy = "cookbook")
public Collection<CookbookSortlevel> getCookbookSortlevels() {
return cookbookSortlevels;
}
public void setCookbookSortlevels(Collection<CookbookSortlevel> cookbookSortlevels) {
this.cookbookSortlevels = cookbookSortlevels;
}
}
#Entity
#Table(name = "cookbook_recipe", schema = "", catalog = "")
public class CookbookRecipe {
private Integer id;
private Recipe recipe;
private Cookbook cookbook;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CookbookRecipe that = (CookbookRecipe) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return true;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
return result;
}
#ManyToOne
#JoinColumn(name = "recipe_id", referencedColumnName = "id")
public Recipe getRecipe() {
return recipe;
}
public void setRecipe(Recipe recipe) {
this.recipe = recipe;
}
#ManyToOne
#JoinColumn(name = "cookbook_id", referencedColumnName = "id", nullable=false,insertable=false,updatable=false )
public Cookbook getCookbook() {
return cookbook;
}
public void setCookbook(Cookbook cookbook) {
this.cookbook = cookbook;
}
}
#Entity
public class Recipe {
private Integer id;
private String title;
private String text;
private Collection<RecipeIngredient> recipeIngredients;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Basic
#Column(name = "title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Basic
#Column(name = "text")
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Recipe recipe = (Recipe) o;
if (id != null ? !id.equals(recipe.id) : recipe.id != null) return false;
if (title != null ? !title.equals(recipe.title) : recipe.title != null) return false;
if (text != null ? !text.equals(recipe.text) : recipe.text != null) return false;
return true;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (text != null ? text.hashCode() : 0);
return result;
}
#OneToMany(mappedBy = "recipe")
public Collection<RecipeIngredient> getRecipeIngredients() {
return recipeIngredients;
}
public void setRecipeIngredients(Collection<RecipeIngredient> recipeIngredients) {
this.recipeIngredients = recipeIngredients;
}
}
Are there any github projects handling this you could suggest?
This is, for me, the right direction. The code looks good
I think you should add it in the CookBookDAO because the Cookbook contains Recipes not the opposite
I have an application (Spring 4 MVC+Hibernate 4+MySQL+Maven integration example using annotations) , integrating Spring with Hibernate using annotation based configuration.
I have this domain object:
#Entity
#Table(name="t_device")
public class Device {
enum Type {
IOS,
ANDROID
}
public Device() {
super();
}
public Device(String key) {
super();
this.key = key;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#NotEmpty
#Size(min=1, max=50)
#Column(name = "device_key", unique=true, nullable = false)
private String key;
#Column(name = "device_desc")
private String desc;
#Enumerated(EnumType.STRING)
#Column(name = "device_type")
private Type type;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "application_id",
referencedColumnName = "id")
private Application application;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Application getApplication() {
return application;
}
public void setApplication(Application application) {
this.application = application;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((desc == null) ? 0 : desc.hashCode());
result = prime * result + id;
result = prime * result + ((key == null) ? 0 : key.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;
Device other = (Device) obj;
if (desc == null) {
if (other.desc != null)
return false;
} else if (!desc.equals(other.desc))
return false;
if (id != other.id)
return false;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
return true;
}
#Override
public String toString() {
return "Device [id=" + id + ", key=" + key + ", desc=" + desc + "]";
}
}
That is linked to this other one:
#Entity
#Table(name="t_device_event")
public class DeviceEvent {
public class Coordinates {
#Column(name = "device_lat")
private Double lat;
#Column(name = "device_lng")
private Double lng;
public Coordinates(Double lat, Double lng) {
super();
this.lat = lat;
this.lng = lng;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne
private Device device;
private Long received;
private String message;
#Transient
private Coordinates coordinates;
public Coordinates getCoordinates() {
return coordinates;
}
public void setCoordinates(Coordinates coordinates) {
this.coordinates = coordinates;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
public Long getReceived() {
return received;
}
public void setReceived(Long received) {
this.received = received;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public DeviceEvent(Device device) {
super();
this.device = device;
}
}
and this piece of code in the controller:
Device device = deviceService.findByKey("AS3989E506");
DeviceEvent deviceEvent = new DeviceEvent(device);
deviceEvent.setCoordinates(deviceEvent.new Coordinates(Double.MIN_VALUE, Double.MAX_VALUE));
deviceEvent.setMessage("message");
deviceEvent.setReceived(new Date().getTime());
deviceEventService.save(deviceEvent);
and the hibernate console:
Hibernate:
select
this_.id as id1_1_1_,
this_.application_id as applicat5_1_1_,
this_.device_desc as device_d2_1_1_,
this_.device_key as device_k3_1_1_,
this_.device_type as device_t4_1_1_,
applicatio2_.id as id1_0_0_,
applicatio2_.application_desc as applicat2_0_0_,
applicatio2_.application_key as applicat3_0_0_
from
t_device this_
left outer join
t_application applicatio2_
on this_.application_id=applicatio2_.id
where
this_.device_key=?
Hibernate:
insert
into
t_device_event
(device_id, message, received)
values
(?, ?, ?)
Hibernate:
select
this_.id as id1_1_1_,
this_.application_id as applicat5_1_1_,
this_.device_desc as device_d2_1_1_,
this_.device_key as device_k3_1_1_,
this_.device_type as device_t4_1_1_,
applicatio2_.id as id1_0_0_,
applicatio2_.application_desc as applicat2_0_0_,
applicatio2_.application_key as applicat3_0_0_
from
t_device this_
left outer join
t_application applicatio2_
on this_.application_id=applicatio2_.id
Here the services:
#Service("deviceEventService")
#Transactional
public class DeviceEventServiceImpl implements DeviceEventService {
#Autowired
private DeviceEventDao dao;
public void save(DeviceEvent deviceEvent) {
dao.save(deviceEvent);
}
}
the other:
#Service("deviceService")
#Transactional
public class DeviceServiceImpl implements DeviceService {
#Autowired
private DeviceDao dao;
public Device findById(int id) {
return dao.findById(id);
}
public void save(Device device) {
dao.save(device);
}
public void update(Device device) {
// TODO Auto-generated method stub
}
public void delete(Device device) {
// TODO Auto-generated method stub
}
public List<Device> findAll() {
return dao.findAll();
}
public Device findByKey(String key) {
return dao.findByKey(key);
}
public boolean isDeviceKeyUnique(Integer id, String key) {
Device device = findByKey(key);
return ( device == null || ((id != null) && (device.getId() == id)));
}
public void deleteByKey(String key) {
dao.deleteByKey (key);
}
}
But the field device_id of the table t_device_event is null !
May be #JoinColumn annotation will help you
#ManyToOne
#JoinColumn(name="device_id")
private Device device;
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.