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.
Related
I work on a Java Spring boot app where I get the error of Hot-swap failed and schema change is not implemented and the operation is not supported by the VM. Afterward, the table is truncated and have no data at all.
I have 2 models provided below,
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
#NotNull
#NotEmpty
private String name;
#Column(name = "countryName")
#NotNull
#NotEmpty
private String countryName;
#Column(name = "currencyName")
#NotNull
#NotEmpty
private String currencyName;
/*
* total steps is for the keepign the history of the user movement
* */
#Column(name = "totalSteps")
#Min(value = 0L, message = "The value must be positive")
private int totalSteps;
/*
* current steps is for providing the user reward. We will need to set
* it to zero after processing the user payment
* */
#Column(name = "currentSteps")
#Min(value = 0L, message = "The value must be positive")
private int currentSteps;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<RewardList> rewardLists = new ArrayList<>();
public User() {
}
public User(#NotNull #NotEmpty String name, #NotNull #NotEmpty String countryName) {
this.name = name;
this.countryName = countryName;
}
public User(#NotNull #NotEmpty String name, #NotNull #NotEmpty String countryName, #Min(value = 0L, message = "The value must be positive") int totalSteps) {
this.name = name;
this.countryName = countryName;
this.totalSteps = totalSteps;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountryName() {
return countryName;
}
public String getCurrencyName() {
return currencyName;
}
public void setCurrencyName(String currencyName) {
this.currencyName = currencyName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public int getTotalSteps() {
return totalSteps;
}
public void setTotalSteps(int totalSteps) {
this.totalSteps = totalSteps;
}
public int getCurrentSteps() {
return currentSteps;
}
public void setCurrentSteps(int currentSteps) {
this.currentSteps = currentSteps;
}
public List<RewardList> getRewardLists() {
return rewardLists;
}
public void setRewardLists(RewardList rl) {
this.rewardLists.add(rl);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return getTotalSteps() == user.getTotalSteps() &&
getCurrentSteps() == user.getCurrentSteps() &&
getId().equals(user.getId()) &&
getName().equals(user.getName()) &&
getCountryName().equals(user.getCountryName()) &&
getRewardLists().equals(user.getRewardLists());
}
#Override
public int hashCode() {
return Objects.hash(getId(), getName(), getCountryName(), getTotalSteps(), getCurrentSteps(), getRewardLists());
}
#Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", countryName='" + countryName + '\'' +
", totalSteps=" + totalSteps +
", currentSteps=" + currentSteps +
'}';
}
}
#Entity
public class RewardList {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "reward")
#Min(value = 0L, message = "The value must be positive")
private double reward;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
private User user;
public RewardList() {
}
public RewardList(User user) {
this.user = user;
}
public RewardList(#Min(value = 0L, message = "The value must be positive") double reward) {
this.reward = reward;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public double getReward() {
return reward;
}
public void setReward(double reward) {
this.reward = reward;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RewardList)) return false;
RewardList list = (RewardList) o;
return Double.compare(list.getReward(), getReward()) == 0 &&
getId().equals(list.getId()) &&
getUser().equals(list.getUser());
}
#Override
public int hashCode() {
return Objects.hash(getId(), getReward(), getUser());
}
#Override
public String toString() {
return "RewardList{" +
"id=" + id +
", reward=" + reward +
", user=" + user +
'}';
}
}
The end-point where I have this issue provided below,
// $ curl -X PUT http://localhost:8080/api/v1/users/calculateReward?userId=1 | jq
#PutMapping("/calculateReward")
public ResponseEntity<Object> calculateReward(#RequestParam("userId") Long userId) {
Optional<User> optional = userService.findById(userId);
if (!optional.isPresent()) {
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
User user = optional.get();
double reward = user.getCurrentSteps() * Parameters.REWARD_PER_STEPS_EUR;
RewardList list = new RewardList();
list.setUser(user);
list.setReward(reward);
rewardListService.save(list);
user.setCurrentSteps(0);
user.setRewardLists(list);
userService.save(user);
JSONObject json = new JSONObject();
double convertionRateToEuro = currencyMap.get(user.getCurrencyName());
double rewardConverted = reward * convertionRateToEuro;
json.put("name", user.getName());
json.put("currency", user.getCurrencyName());
json.put("reward", rewardConverted);
return ResponseEntity.status(HttpStatus.CREATED).body(json);
}
Does anyone know what is going on and can provide a solution?
Thank you.
I find the reason and below I provide a solution. We will need to save the models based on the hierarchy. HotSwap doesn't support adding methods or hierarchy changes as indicated by the error messages. It's the limitation of Java HotSwap, not IntelliJ IDEA. The proper way of code sequence will be,
User user = optional.get();
RewardList list = new RewardList();
list.setUser(user);
list.setReward(reward);
user.setCurrentSteps(0);
user.setRewardLists(list);
// first save the User
userService.save(user);
// Then, save the RewardList as it has one to many relations
rewardListService.save(list);
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 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.
I have three entities: Account, AccountAttribut and Attribut. Account and Attribut are associated via AccountAttribut in a many-to-many relationship like it is described here (1). AccountAttribut is a join table entity that holds an additional attribute.
I try to build a HQL string that delivers all Accounts with the "wert"-property "John" in AccountAttribut and the name-property "FirstName" in Attribut.
I dont find the right HQL string. Can you help me out?
(1): http://giannigar.wordpress.com/2009/09/04/mapping-a-many-to-many-join-table-with-extra-column-using-jpa/ "Mapping a many-to-many join table with extra column using JPA"
I tried this query:
List<Account> queried_accounts = HibernateUtils.queryList(
session.createQuery(""
+ "from Account as acc"
+ " full join acc.accountAttributes as accAtt"
+ " inner join accAtt.aa_pk.attribut as attr"
+ " where attr.name='FirstName' and accAtt.wert='John'")
);
and i get this error message:
ERROR: You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'full outer join account_attribut accountatt1_ on
account0_.account_id=accountatt' at line 1
UPDATE:
I changed the query to:
List<Account> queried_accounts = HibernateUtils.queryList(
session.createQuery(""
+ "from Account as acc"
+ " inner join acc.accountAttributes as accAtt"
+ " inner join accAtt.aa_pk.attribut as attr"
+ " where attr.name='FirstName' and accAtt.wert='John'")
);
This seems to work.
But now i got a new Problem: queried_accounts does not seem to be a List of Accounts. If i get an object out of queried_accounts and try to apply account methods on it, i get an Exception at runtime.
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to
com.computacenter.qct.pojos.Account
These are relevant code extracts:
Account:
#Entity
#Table(name = "account")
public class Account {
private Long accountId;
private List<AccountAttribut> accountAttributes = new LinkedList<AccountAttribut>();
private Person person;
private Zielsystem zielsystem;
public Account() {
}
#Id
#GeneratedValue
#Column(name = "account_id", nullable = false)
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "aa_pk.account", cascade = {
CascadeType.PERSIST, CascadeType.MERGE })
#Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE,
org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public List<AccountAttribut> getAccountAttributes() {
return accountAttributes;
}
public void setAccountAttributes(List<AccountAttribut> accountAttribute) {
this.accountAttributes = accountAttribute;
}
#ManyToOne
#JoinColumn(name = "person_id")
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
#ManyToOne
#JoinColumn(name="zielsystem_id")
public Zielsystem getZielsystem() {
return zielsystem;
}
public void setZielsystem(Zielsystem zielsystem) {
this.zielsystem = zielsystem;
}
}
AccountAttribut:
#Entity
#Table(name="account_attribut")
#AssociationOverrides({
#AssociationOverride(name="aa_pk.account", joinColumns = #JoinColumn(name="account_id")),
#AssociationOverride(name="aa_pk.attribut", joinColumns = #JoinColumn(name="attribut_id"))
})
public class AccountAttribut {}
private AccountAttributPk aa_pk = new AccountAttributPk();
#Column(name="wert")
private String wert;
#EmbeddedId
public AccountAttributPk getAa_pk() {
return aa_pk;
}
public void setAa_pk(AccountAttributPk aa_pk) {
this.aa_pk = aa_pk;
}
#Transient
public Account getAccount() {
return getAa_pk().getAccount();
}
public void setAccount(Account account) {
getAa_pk().setAccount(account);
}
#Transient
public Attribut getAttribut() {
return getAa_pk().getAttribut();
}
public void setAttribut(Attribut attribut) {
getAa_pk().setAttribut(attribut);
}
public String getWert() {
return wert;
}
public void setWert(String wert) {
this.wert = wert;
}
public boolean equals(Object o) {
if (this== o) return true;
if (o ==null|| getClass() != o.getClass()) return false;
AccountAttribut that = (AccountAttribut) o;
if (getAa_pk() !=null?!getAa_pk().equals(that.getAa_pk()) : that.getAa_pk() !=null) return false;
return true;
}
public int hashCode() {
return (getAa_pk() !=null? getAa_pk().hashCode() : 0);
}
}
AccountAttributPk:
public class AccountAttributPk implements Serializable {
private static final long serialVersionUID = -1551814445010872872L;
private Account account;
private Attribut attribut;
#ManyToOne
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
#ManyToOne
public Attribut getAttribut() {
return attribut;
}
public void setAttribut(Attribut attribut) {
this.attribut = attribut;
}
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
AccountAttributPk that = (AccountAttributPk) o;
if (account != null ? !account.equals(that.account) : that.account != null)
return false;
if (attribut != null ? !attribut.equals(that.attribut)
: that.attribut != null)
return false;
return true;
}
public int hashCode() {
int result;
result = (account != null ? account.hashCode() : 0);
result = 31 * result + (attribut != null ? attribut.hashCode() : 0);
return result;
}
}
Attribut
#Entity
#Table(name="Attribut")
public class Attribut {
private Long attributId;
private String name;
private List<PersonAttribut> personenAttribute = new LinkedList<PersonAttribut>();
private List<AccountAttribut> accountAttribute = new LinkedList<AccountAttribut>();
private List<BerechtigungsobjektAttribut> berechtigungsobjektAttribute = new LinkedList<BerechtigungsobjektAttribut>();
public Attribut() {}
public Attribut(String name) {
this.name = name;
}
#Id
#GenericGenerator(name="generator", strategy="increment")
#GeneratedValue(generator="generator")
#Column(name="attribut_id", nullable=false)
public Long getAttributId() {
return attributId;
}
public void setAttributId(Long attributId) {
this.attributId = attributId;
}
#Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pa_pk.attribut", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
public List<PersonAttribut> getPersonenAttribute() {
return personenAttribute;
}
public void setPersonenAttribute(List<PersonAttribut> personenAttribute) {
this.personenAttribute = personenAttribute;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "aa_pk.attribut", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
public List<AccountAttribut> getAccountAttribute() {
return accountAttribute;
}
public void setAccountAttribute(List<AccountAttribut> accountAttribute) {
this.accountAttribute = accountAttribute;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "ba_pk.attribut", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
public List<BerechtigungsobjektAttribut> getBerechtigungsobjektAttribute() {
return berechtigungsobjektAttribute;
}
public void setBerechtigungsobjektAttribute(
List<BerechtigungsobjektAttribut> berechtigungsobjektAttribute) {
this.berechtigungsobjektAttribute = berechtigungsobjektAttribute;
}
#Override
public String toString() {
return name;
}
#Override
public boolean equals(Object other) {
if (other == null)
return false;
if (this == other)
return true;
if (this.getClass() != other.getClass())
return false;
final Attribut otherAccount = (Attribut) other;
return EqualsUtils.nullSafeEquals(this.getName(), otherAccount.getName());
}
#Override
public int hashCode() {
final int PRIME = 42;
return this.name.hashCode() * PRIME;
}
}