How to apply hibernate annotations to the child class of abstract class - java

I have an abstract class named Staff. Instructor and Lecturer are the derived classes from the Staff superclasses. I need to use hibernate annotations into the Instructor and Lecturer classes.
Staff.java
public abstract class Staff {
private int staffID;
private String firstName;
private String lastName;
private String mobile;
private String email;
private double salary;
private String city;
private String street;
//getters and setters
}
This is the subclass and I used staffID again in the subclass to apply the #Id annotation.
Lecturer.java
#Entity
#Table(name = "lecturer")
public class Lecturer extends Staff {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int staffID;
private int lectureHours;
public int getLectureHours() {
return lectureHours;
}
public void setLectureHours(int lectureHours) {
this.lectureHours = lectureHours;
}
}
I used the service classes and controllers and the JPARepositories as usually. but the database table only contain 2 values fields only (staffID and lectureHours). as follows.
LecturerRepository.java
package com.example.backend.admin.Repositories;
import com.example.backend.admin.models.Lecturer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface LecturerRepository extends JpaRepository<Lecturer, Integer> {
}
LecturerController.java
#RestController
#RequestMapping("/lecturers")
public class LecturerController {
private static Logger logger = LoggerFactory.getLogger(LecturerController.class);
#Autowired
LecturerService lecturerService;
/**
* to insert a new lecturer
* #param lecturer new lecturer
* #return insert lecturer
*/
#PostMapping("/add")
public Lecturer addLecturer(#RequestBody Lecturer lecturer) {
Lecturer lecturer1 = null;
try {
lecturer1 = lecturerService.addLecturer(lecturer);
} catch (NullPointerException e) {
logger.error("check the payload, null pointer is throwing", e);
}
return lecturer1;
}
}
LecturerService.java
#Service
public class LecturerService {
#Autowired
LecturerRepository lecturerRepository;
/**
* to invoke save method in jpa
* #param lecturer new lecturer
* #return inserted lecturer
*/
public Lecturer addLecturer(Lecturer lecturer){
return lecturerRepository.save(lecturer);
}
}
I want to add all the fields of the Lecturer class into the database. So what should I do for that?

You need to annotate the abstract class with #MappedSuperclass, in this way your #Entity class will inherit all the attributes from the extended class.

Related

Does Eclipse option generate entities from tables generate POJO object or BEAN object?

I am working on one Java project in Eclipse, which uses database with some tables inside it. Initially I used Eclipse option generate entities from tables. Because I have to write something about mu work on this project, I am wondering which type of Java class is generated during this process? Is it Bean or POJO? I think it's Bean because it implements Serializable class, because I think that I had read somewhere that POJO should not extend or implement other predefined classes like Serializable, but I think it's better to ask, than to be sorry later, please correct me if I'm wrong.
Here is an example of one of the classes:
package modeli;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the člankomisije database table.
*
*/
#Entity
#NamedQuery(name="Člankomisije.findAll", query="SELECT č FROM Člankomisije č")
public class Člankomisije implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int idČlanKomisije;
private String vrstaČlana;
//bi-directional one-to-one association to Ocjenjujetemu
#OneToOne(mappedBy="člankomisije")
private Ocjenjujetemu ocjenjujetemu;
//bi-directional many-to-one association to Zapisnik
#OneToMany(mappedBy="člankomisije")
private List<Zapisnik> zapisniks;
//bi-directional many-to-one association to Komisija
#ManyToOne
#JoinColumn(name="idKomisija")
private Komisija komisija;
//bi-directional many-to-one association to Nastavnik
#ManyToOne
#JoinColumn(name="idNastavnik")
private Nastavnik nastavnik;
public Člankomisije() {
}
public int getIdČlanKomisije() {
return this.idČlanKomisije;
}
public void setIdČlanKomisije(int idČlanKomisije) {
this.idČlanKomisije = idČlanKomisije;
}
public String getVrstaČlana() {
return this.vrstaČlana;
}
public void setVrstaČlana(String vrstaČlana) {
this.vrstaČlana = vrstaČlana;
}
public Ocjenjujetemu getOcjenjujetemu() {
return this.ocjenjujetemu;
}
public void setOcjenjujetemu(Ocjenjujetemu ocjenjujetemu) {
this.ocjenjujetemu = ocjenjujetemu;
}
public List<Zapisnik> getZapisniks() {
return this.zapisniks;
}
public void setZapisniks(List<Zapisnik> zapisniks) {
this.zapisniks = zapisniks;
}
public Zapisnik addZapisnik(Zapisnik zapisnik) {
getZapisniks().add(zapisnik);
zapisnik.setČlankomisije(this);
return zapisnik;
}
public Zapisnik removeZapisnik(Zapisnik zapisnik) {
getZapisniks().remove(zapisnik);
zapisnik.setČlankomisije(null);
return zapisnik;
}
public Komisija getKomisija() {
return this.komisija;
}
public void setKomisija(Komisija komisija) {
this.komisija = komisija;
}
public Nastavnik getNastavnik() {
return this.nastavnik;
}
public void setNastavnik(Nastavnik nastavnik) {
this.nastavnik = nastavnik;
}
}

How to get subclasses attributes using SingleTableInheritance with SpringMVC

i am working on a web application using Spring, Hibernate and SpringMVC,
i am facing a problem with retreiving values from a subclass table using SingleTable inheritance strategy, here are my entities
Client.java (Super class)
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "typeClient", discriminatorType = DiscriminatorType.STRING)
public class Client implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idClient;
private String matricule;
private String statut;
private String secteurDactivite;
private String nomClient;
private String emailClient;
private String numTelephone;
private String adresse;
//constructor
//getter & setters
}
Societe.java (subClass1)
#Entity
#DiscriminatorValue("Societe")
public class Societe extends Client implements Serializable{
private String nomResponsable;
private String emailResponsable;
private String telResponsable;
private String nomSuperieur;
private String emailSuperieur;
private String telSuperieur;
private String commentaire;
//constructeur sans parametre
public Societe() {
}
}
Particulier.java (subclass2)
#Entity
#DiscriminatorValue("Particulier")
public class Particulier extends Client implements Serializable {
private String cin;
//constructeur sans parametres
public Particulier() {
}
}
in my implementation i am using this methode to get a particular client with his ID
ClientDaoImpl.java
public class ClientDaoImpl implements ClientDao {
#PersistenceContext
private EntityManager em;
#Override
public Client getClientByID(int id_client) {
return em.find(Client.class, id_client);
}
When i ran this code i only selected the attributes of the superClass Client.
what i am trying to do is to get a client with its subclass whether it's a Societe or Particulier based on its type or clientID.
Please Help
As you don't know the type of client before querying and only it's ID, you will need to inspect the type and cast after you retrieve the record;
Client client1 = clientDao.getClientById(clientID);
if (client1 instanceof Societe) {
((Societe) client1).getCommentaire();
}
Depending on your use case, it may be useful to map the result of the client query to a ClientDescriptor object which contains all the fields for all client types and returns either nulls or blanks. This means you don't have to keep checking for client type everywhere;
public class ClientDTO {
//client fields
private String nomResponsable = "";
....
//subclass 1 fields.... initialize to empty
//subclass 2 fields .... initialize to empty
public ClientDTO (Client client) {
// set fields for client entity
}
public ClientDTO (Societe societe) {
this (societe);
// set societe fields.
}
// other constructors.
}
You can modify your getClientByID method to accept an additional argument which will say what type of entity your want to retrieve and get back:
public class ClientDaoImpl implements ClientDao {
#PersistenceContext
private EntityManager em;
public <T extends Client> T getByID(int id_client, Class<T> klass) {
return em.find(klass, id_client);
}
}
And you can use this dao in the following manner:
Societe societe = clientDao.getByID(42, Societe.class);
Particulier particulier = clientDao.getByID(43, Particulier.class);

how to set a generic implementation of JpaRepository interface for all entities?

Here is my project structure:
An #MappedSuperclass base class:
#MappedSuperclass
public class BaseClass {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;
//getter and setter
}
An #Entity extending the base class:
#Entity
public class Person extends BaseClass {
private String regisNumber;
private String name;
private int hPerWeek;
/**
* #param regisNumber
* #param name
* #param hPerWeek
*/
public Person(String regisNumber, String name, int hPerWeek) {
super();
this.regisNumber = regisNumber;
this.name = name;
this.hPerWeek = hPerWeek;
}
//getters and setters
}
The generic DAO:
#Repository
public interface IDao<T extends BaseClass> extends JpaRepository<T, Long> {
}
In my tests, creating a Person works fine:
#Autowired
IDao<Person> dao;
#Test
public void whenPersonEntityIsCreated_thenNoExceptions() {
Person person = new Person("mkd90ii", "manu", 24);
dao.save(person);
}
Nevertheless trying getting a Person :
#Test
public void whenPersonEntityIsUpdated_thenNoExceptions() {
Person person = dao.getOne(Long.valueOf(32768));
System.out.println(person.toString());
//Updating person...
}
generates me this error:
org.springframework.dao.InvalidDataAccessApiUsageException: Unknown entity: com.bockmoi.entities.BaseClass;
nested exception is java.lang.IllegalArgumentException: Unknown entity: com.bockmoi.entities.BaseClass
I do understand that's because BaseClass is not a javax.persistence.Entity, but why the creation works and not the reading?
Can someone explain me why this happens and how to overcome this?
It's a kind of dead end for me.
Thanks

Entity with Inner class for building the entity

I am trying out one-to-one mapping in JPA,
here i have taken relationship between Student and Contact, each student has an contact.
i have create Student entity as follows,
#Entity
#Table(name="TBL_STUDENT")
public class Student implements Serializable{
public Student(){ }
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID")
private Integer studentId;
#OneToOne(targetEntity=StudentContact.class,fetch=FetchType.LAZY)
#JoinColumn(name="CONTACT_ID")
private StudentContact contact;
....
....
....
}
Now the StudentContact entity as follows,
#Entity
#Table(name="TBL_STD_CONTACT")
public class StudentContact extends Serializable{
public StudentContact(){ }
#Id
#Column(name="ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer contactId;
...
...
// all the properties mapped,
public static class Builder{
private Integer contactId;
private String phoneNo;
private String streetAddr;
....
// all the properties as same as StudentContact
public Builder(String val){
this.city = val;
}
public Builder setContactId(Integer contactId) {
this.contactId = contactId;
return this;
}
// rest all the setter methods are like the above, having return type Builder
public StudentContact build(){
return new StudentContact(this);
}
}
private StudentContact(Builder builder){
this.contactId = builder.contactId;
this.city = builder.city;
this.phoneNo = builder.phoneNo;
.......
...
}
}
In the above StudentContact Entity you can see i have created an inner class Builder, whose responsibility is to build StudentContact object by using its "build" method, which you can see in below mentioned StudentTest class
Now i have written a StudentTest class which has the main method as follows,
public class StudentTest {
public static void main(String [] args){
try{
StudentDAO dao = new StudentDAO();
Student student = dao.getEntity(110);
StudentContact contact = new StudentContact.Builder("Bhubaneshwar")
.setPhoneNo("9867342313")
.setPinCode("400392")
.setState("Odhisha").build();
student.setContact(contact);
dao.updateEntity(student);
}catch(Exception e){
e.printStackTrace();
}
}
When i run StudentTest from netbeans IDE, it gives as error
Exception in thread "main" java.lang.VerifyError: Constructor must call super() or this() before return in method com.entities.StudentContact.<init>()V at offset 0
I am not able to understand this error, whether this error is because for the inner class which i have created in StudentContact class,
How can i solve this,
java.lang.VerifyError means that the bytecode is not correct. Usually it can be fixed with a full clean/rebuild of the project. (I sometimes saw it after package/class renaming, or class moving from one package to another).
As mentionned in comments : extends Serializable is not correct. (maybe the cause of your bytecode issue ?)

Hibernate JPA: mappedBy reference exception

I want to map the following classes with Hibernate JPA:
My code looks like this:
#Entity
public class Grid{
#Id
#GeneratedValue
private Long id;
#Column(unique=true)
private String name;
private String location;
private BigDecimal costsPerCPUMinute;
#OneToMany(mappedBy="grid")
private List<Membership> mem;
public List<Membership> getMem() {
return mem;
}
public void setMem(List<Membership> mem) {
this.mem = mem;
}
#Entity
public class User extends Person{
#Column(nullable=false, unique=true)
private String username;
#Column(length=16,columnDefinition="BINARY(16)")
private byte[] password;
#OneToMany(mappedBy="user")
private List<Membership> mem;
public List<Membership> getMem() {
return mem;
}
public void setMem(List<Membership> mem) {
this.mem = mem;
}
#SuppressWarnings("serial")
#Entity
public class Membership implements Serializable{
private Date registration;
private Double discount;
#Id
#ManyToOne
private Grid grid;
#Id
#ManyToOne
private User user;
public Grid getGrid() {
return grid;
}
public void setGrid(Grid grid) {
this.grid = grid;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
Unfortunately, I get the following Exception:
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: dst1.model.Membership.grid in dst1.model.Grid.mem
As far as I understand the message, grid cannot be found in Membership. But as you can see in de code, there definitly is a variable named grid in the Membership class.
Does anybody has an idea whats going wrong?
Update: As suggested in the comments, I also tried to change the Membership Class by using IDClass or EmbeddedID. The EmbeddedID version looks like this:
#SuppressWarnings("serial")
#Entity
public class Membership implements Serializable{
private Date registration;
private Double discount;
#EmbeddedId
private MembershipPK membershipPK;
public Membership(){};
public MembershipPK getMembershipPK() {
return membershipPK;
}
public void setMembershipPK(MembershipPK membershipPK) {
this.membershipPK = membershipPK;
}
#SuppressWarnings("serial")
#Embeddable
public class MembershipPK implements Serializable{
#ManyToOne
private Grid grid;
#ManyToOne
private User user;
public Grid getGrid() {
return grid;
}
public void setGrid(Grid grid) {
this.grid = grid;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Unfortunately, I still get the same exception.
Update 2: I will rewrite all three classes from scratch tomorrow evening and update this post if that changes anything.
You should be able to use something like
#Embeddable
public class MembershipId
{
protected Grid grid;
protected User user;
}
#Entity
public class Membership {
#EmbeddedId
MembershipId id;
}
#Entity
public class User {
#OneToMany(mappedBy="id.user")
private Set<Membership> memberships = new HashSet<Membership>();
}
From the top of my head: shouldn't this be rather
public class MembershipId implements Serializable {
private Grid grid;
private User user;
// immutable constructor, getters, equals, and hashCode
}
#Entity
#IdClass(MembershipId.class)
public class Membership implements Serializable {
#Id #ManyToOne
private Grid grid;
#Id #ManyToOne
private User user;
// rest of class
}
Edit: What the exception is telling you is that your Grid class has a field named mem and that the entity represented by this field needs a grid field, but doesn't have one. Here is where your Grid.mem needs a grid field:
#Entity
public class Grid{
...
#OneToMany(mappedBy="grid")
private List<Membership> mem;
This mapping can only work if there is a property grid in Membership.class. If you hide the grid inside the IdClass, Grid.mem can't find it. You might try this:
#Embeddable
public class MembershipId implements Serializable {
private Grid grid;
private User user;
// immutable constructor, getters, equals, and hashCode
}
#Entity
public class Membership implements Serializable {
#EmbeddedId
private MembershipId id;
#ManyToOne
private Grid grid;
#ManyToOne
private User user;
// rest of class
}

Categories

Resources