Hibernate one to one mapping with composed key doesn't work - java

I have one-to-one hibernate mapping between class Report and class Flyleaf.
The listed code is successfully executed and the mapping works good.
In my real model the primary key of a report is composed of an "id" and an "index" and so does flyleaf (because its primary key is the primary key of a report).
How can I change my code in order to make the primary key composite (I tried, but an exception was thrown when I want to get list of reports and I also tried to define the key as a PKClass).
(I'm using Hibernate and Spring if this can help)
#Entity
#Table(name="report_t")
public class Report {
private int id, nbPage;
private Flyleaf flyleaf;
public Report() {}
public Report(int id) {
this.id = id;
}
#Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name="nb_page")
public int getNbPage() {
return nbPage;
}
public void setNbPage(int nbPage) {
this.nbPage = nbPage;
}
#OneToOne (fetch = FetchType.LAZY, mappedBy = "report", cascade = CascadeType.ALL)
public Flyleaf getFlyleaf() {
return flyleaf;
}
public void setFlyleaf(Flyleaf flyleaf) {
this.flyleaf = flyleaf;
}
#Override
public String toString() {
return "ID : "+id+"\t nb page : "+nbPage+"\n\t"+flyleaf;
}
}
#Entity
#Table(name="flyleaf_t")
public class Flyleaf {
private int id;
private String title, author, checker;
private Report report;
public Flyleaf() {}
public Flyleaf(int id) {
this.id = id;
}
#GenericGenerator(name = "generator", strategy = "foreign",
parameters = #Parameter(name = "property", value = "report_t"))
#Id
#GeneratedValue(generator = "generator")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column (name="title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Column (name="author")
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
#Column (name="checker")
public String getChecker() {
return checker;
}
public void setChecker(String checker) {
this.checker = checker;
}
#OneToOne(fetch = FetchType.LAZY)
#PrimaryKeyJoinColumn
public Report getReport() {
return report;
}
public void setReport(Report report) {
this.report = report;
}
#Override
public String toString() {
return "Flyleaf [id=" + id + ", title=" + title + ", author="
+ author + ", checker=" + checker + "]";
}
}

Related

H2 ERROR: Referential integrity constraint violation - Hibernate one to one mapping

I have two entity (Instructor, InstructorDetail) which have one to one relation.
instructor_detail_id of Instructor entity has a foreign key to the id column of InstructorDetail. So, according to my requirement, when an Instructor is deleted, corresponding instructorDetail also needs to be deleted, but not the vice versa. Now, when I am trying to delete an instructorDetail, it is throwing the referencial integrity constraint error.
Note: I am using H2 db.
Following are the code snippets.
Instructor -
import javax.persistence.*;
#Table(name="instructor")
#Entity
public class Instructor implements IdentityMarker<Integer>{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="instructor_id")
private int id;
#Column(name="name")
private String name;
#Column(name="email")
private String email;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "instructor_detail_id")//, referencedColumnName = "id")
private InstructorDetail instructorDetail;
public Instructor(){
}
public Instructor(String name, String email) {
this.name = name;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public InstructorDetail getInstructorDetail() {
return instructorDetail;
}
public void setInstructorDetail(InstructorDetail instructorDetail) {
this.instructorDetail = instructorDetail;
}
public Integer getReference() {
return id;
}
public void setReference(Integer id){ this.id = id;}
#Override
public String toString() {
return "Instructor{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", instructorDetail=" + instructorDetail +
'}';
}
}
InstructorDetail -
import javax.persistence.*;
#Table(name="instructor_detail")
#Entity
public class InstructorDetail implements IdentityMarker<Integer>{
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name="youtube_link")
private String youtubeLink;
#Column(name="hobby")
private String hobby;
#OneToOne(cascade = {
CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH
},
mappedBy = "instructorDetail")
// this bi-directional relationship enables us to get the instructor when an instructionDetail is loaded.
private Instructor instructor;
public InstructorDetail(){
}
public InstructorDetail(String youtubeLink, String hobby){
this.youtubeLink = youtubeLink;
this.hobby = hobby;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getYoutubeLink() {
return youtubeLink;
}
public void setYoutubeLink(String youtubeLink) {
this.youtubeLink = youtubeLink;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public Instructor getInstructor() {
return instructor;
}
public void setInstructor(Instructor instructor) {
this.instructor = instructor;
}
public Integer getReference() {
return id;
}
public void setReference(Integer id){ this.id = id;}
#Override
public String toString() {
return "InstructorDetail{" +
"id=" + id +
", youtubeLink='" + youtubeLink + '\'' +
", hobby='" + hobby + '\''+
'}';
}
#PreRemove
private void preRemove() {
System.out.println("pre remove call");
instructor.setInstructorDetail(null);
}
}
Following is the client code
private static void deleteInstructorDetail(){
InstructorDetailDao instructorDetailDao = new InstructorDetailDaoImpl();
InstructorDetail instructorDetail = instructorDetailDao.getInstructorDetail(2);
Instructor instructor = instructorDetail.getInstructor();
System.out.println("Instructor: " + instructor);
boolean b = instructorDetailDao.deleteInstructorDetail(instructorDetail);
assert b == true: "InstructorDetail is not deleted!";
System.out.println("Trying to load Instructor.. It should be deleted!");
InstructorDao instructorDao = new InstructorDaoImpl();
instructor = instructorDao.getInstructor(instructor.getId());
assert instructor != null: "Instructor also got deleted!";
}
Any help would be appreciated! Thanks in advance.

Are entities relationship correct?

In my project I try yo use Spring data Jpa. My find methods(findById, findAll) works correctly, but delete and save method works with problems. Delete method delete only from duck table. Save doesn't work:
Exception in thread "main" org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find springdata.entities.FrogJpa with id 2; nested exception is javax.persistence.EntityNotFoundException: Unable to find springdata.entities.FrogJpa with id 2
I have 2 entities: Frog and Duck. Every ducks have 1 Frog(OneToOne). There are problems with entities relationship?
There are my entities class:
#Entity
#Table(name = "DUCKS")
public class DuckJpa implements Serializable {
#Id
private int id;
#Column(name = "NAME")
private String name;
#Column(name = "FLY")
private String flyBehavior;
#Column(name = "QUACK")
private String quackBehavior;
#OneToOne(optional = false)
#JoinColumn(name = "FROG_ID", unique = true, nullable = false, updatable = false)
private FrogJpa frogJpa;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setFlyBehavior(String flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(String quackBehavior) {
this.quackBehavior = quackBehavior;
}
public void setFrogJpa(FrogJpa frogJpa) {
this.frogJpa = frogJpa;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getFlyBehavior() {
return flyBehavior;
}
public String getQuackBehavior() {
return quackBehavior;
}
public FrogJpa getFrogJpa() {
return frogJpa;
}
And Frog:
#Entity
#Table(name = "FROGS")
public class FrogJpa {
#OneToOne(optional = false, mappedBy = "frogJpa")
private DuckJpa duckJpa;
#Id
private int id;
#Column(name = "name")
private String name;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDuckJpa(DuckJpa duckJpa) {
this.duckJpa = duckJpa;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public DuckJpa getDuckJpa() {
return duckJpa;
}
}
My service class:
public interface DuckService {
List<DuckJpa> findAll();
Optional<DuckJpa> findById(Integer i);
DuckJpa save(DuckJpa duckJpa);
void delete(DuckJpa duckJpa);
}
And it's implementation:
#Service("springJpaDuckService")
#Transactional
public class DuckServiceImpl implements DuckService {
#Autowired
private DuckJpaRepository duckJpaRepository;
#Transactional(readOnly = true)
public List<DuckJpa> findAll() {
return new ArrayList<>(duckJpaRepository.findAll());
}
#Override
public Optional<DuckJpa> findById(Integer i) {
return duckJpaRepository.findById(i);
}
#Override
public DuckJpa save(DuckJpa duckJpa) {
duckJpaRepository.save(duckJpa);
return duckJpa;
}
#Override
public void delete(DuckJpa duckJpa) {
duckJpaRepository.delete(duckJpa);
}
Use #OneToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY).
For more information please refer What is cascading in Hibernate?

issue with Criteria when making an association on 2 tables with a fereign key

I m trying to learn about hibernate and Criteria.
i have 2 tables RATS and SICKNESS.
I set a foreign key in RATS : RATS.Sickness_Id = SICKNESS.ID.
I m trying to get with Criteria an equivalent of SQL:
select * from RATS r, SICKNESS s where s.id = r.sickness_id
I assumed it was this association:
session
.createCriteria(Rats.class)
.createCriteria(Sickness.class)
.toList()
This unfortunately ends up with:
org.hibernate.QueryException: could not resolve property: entities of: entities.Rats
Strange part is that both:
session.createCriteria(Rats.class).toList()
and
session.createCriteria(Sickness.class).toList()
work fine....
I'm a bit puzzled.
Here are my entities classes code:
#Entity
#Table(name = "RATS")
public class Rats implements java.io.Serializable {
private int id;
private Sickness sickness;
private String name;
private int age;
public Rats() {
}
public Rats(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Rats(int id, Sickness sickness, String name, int age) {
this.id = id;
this.sickness = sickness;
this.name = name;
this.age = age;
}
#Id
#Column(name = "ID", unique = true, nullable = false)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "Sickness_Id")
public Sickness getSickness() {
return this.sickness;
}
public void setSickness(Sickness sickness) {
this.sickness = sickness;
}
#Column(name = "Name", nullable = false, length = 50)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "Age", nullable = false)
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public String toString() {
String returnString = "My name is " + getName() + ", I am " + getAge()+ ". ";
returnString += getSickness() == null ? "I am healthy like hell! :)" : "I suffer from " + getSickness().getNom();
return returnString;
}
}
and
#Entity
#Table(name = "SICKNESS")
public class Sickness implements java.io.Serializable {
private int id;
private String nom;
private Set<Rats> ratses = new HashSet<Rats>(0);
public Sickness() {
}
public Sickness(int id) {
this.id = id;
}
public Sickness(int id, String nom, Set<Rats> ratses) {
this.id = id;
this.nom = nom;
this.ratses = ratses;
}
#Id
#Column(name = "Id", unique = true, nullable = false)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
#Column(name = "Nom", length = 50)
public String getNom() {
return this.nom;
}
public void setNom(String nom) {
this.nom = nom;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "sickness")
public Set<Rats> getRatses() {
return this.ratses;
}
public void setRatses(Set<Rats> ratses) {
this.ratses = ratses;
}
#Override
public String toString() {
return getNom()
+ ( getRatses() != null ? (", getRatses()=" + getRatses() + "]"): "" );
}
}
What did I miss?
Thanks in advance.
On Rats entity, the Sickness entity property is:
private Sickness sickness;
Accordingly, your association must use the same name.
session.createCriteria(Rats.class)
.createCriteria("sickness")
.list();
One other solution, should be to change Rats to use EAGER Fetch:
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "Sickness_Id")
public Sickness getSickness() {
return this.sickness;
}
public void setSickness(Sickness sickness) {
this.sickness = sickness;
}
and then use:
session.createCriteria(Rats.class)
.list();

Caused by: java.sql.SQLSyntaxErrorException: ORA-01722: invalid number in JPA HIBERNATE HQL

Having this class
#Entity
public class PriorityAreaKeyword {
public enum PriorityAreaKey {
ALL ("ALL", "ALL DEVICES"),
IOS ("IOS", "IOS"),
ANDROID ("ANDROID","ANDROID");
private final String name;
private final String id;
private PriorityAreaKey(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
}
#Id
private Long id;
#Column(name = "key")
#Enumerated(EnumType.STRING)
private PriorityAreaKey key;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public PriorityAreaKey getKey() {
return key;
}
public void setKey(PriorityAreaKey key) {
this.key = key;
}
public List<PriorityArea> getPriorityAreas() {
return priorityAreas;
}
public void setPriorityAreas(List<PriorityArea> priorityAreas) {
this.priorityAreas = priorityAreas;
}
}
I have in the DAO this method that is working fine:
#Override
#SuppressWarnings("unchecked")
public Set<PriorityArea> findPriorityAreas(PriorityAreaKey key) {
String jpql = "from PriorityAreaKeyword as pak where pak.key = :key";
Query query = entityManager.createQuery(jpql);
query.setParameter("key", key);
List<PriorityArea> priorityAreas = query.getResultList();
return new HashSet<PriorityArea>(priorityAreas);
}
I created a view like this v_report_beneficiary_list (id, email, priority_area_key)
/**
*
*/
#Entity
#Table(name = "v_report_beneficiary_list")
public class ReportBeneficiaryItem {
private Long id;
private String email;
private PriorityAreaKey priorityAreaKey;
/**
* #return the id
*/
#Id
public Long getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
#Column(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name = "priority_area_key")
public PriorityAreaKey getPriorityAreaKey() {
return priorityAreaKey;
}
public void setPriorityAreaKey(PriorityAreaKey priorityAreaKey) {
this.priorityAreaKey = priorityAreaKey;
}
In the DAO I've created another method like this:
#Su
ppressWarnings("unchecked")
#Override
public List<ReportBeneficiaryItem> findReportProposalXBeneficiary(ProposalExportFilter filter) {
// Create basic query
String jpql = "from " + ReportBeneficiaryItem.class.getName() + " b where b.priorityAreaKey = :key ";
// Create and execute jpa query
Query query = createQuery(jpql);
query.setParameter("key", filter.getPriorityAreaKey());
return query.getResultList();
}
That throws me a throws me an Exception Caused By: java.sql.SQLSyntaxErrorException: ORA-01722: invalid number
You are missing #Enumerated(EnumType.STRING) on ReportBeneficiaryItem#getPriorityAreaKey() as you have on PriorityAreaKeyword#key, so it's expecting numbers (enum index) in the database for that field, but finds strings
#Column(name = "priority_area_key")
#Enumerated(EnumType.STRING)
public PriorityAreaKey getPriorityAreaKey() {
return priorityAreaKey;
}

how to avoid getting null value in foregin key value in db using jpa?

iam getting foregin key value null in db.iam using jpa.
i have two tables,one is user another one is review.i want to store user id value in review table.review table iam getting null for user_id column.plz help me how to store the user id value ...
thanks
this is my api class for user
public interface User
{
public int getId();
public void setId(int id);
public String getFirstName();
public void setFirstName(String firstName);
public String getLastName();
public void setLastName(String lastName);
}
and this is my review api class
public interface Review
{
public int getId();
public void setId(int id);
public String getReview();
public void setReview(String review);
public User getUserId();
public void setUserId(User userId);
}
and this is my model class for review
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
#Basic(optional = true)
#Column(name = "reviews")
private String review;
public String getReview()
{
return review;
}
public void setReview(String review)
{
this.review = review;
}
#OneToOne(targetEntity = com.movi.db.model.UserImpl.class, cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private User userId;
public User getUserId()
{
return userId;
}
public void setUserId(User userId)
{
this.userId = userId;
}
this is my my dao method
public boolean createReview(Review review)
{
em.getTransaction().begin();
em.persist(review);
em.getTransaction().commit();
return true;
}
this is my action class
private ReviewImpl review;
private String userReview;
private String reply;
private String send;
private User user;
//setters and getters
if(reply!=null)
{
review.setUserId(user);
if(service.createReview(review))
System.out.println("created review successful");
else
System.out.println("creation failed");
return "userreview";
}

Categories