I know English badly, but i'm trying to describe my problem.
I'm new in Spring. And I have some problems with adding data to my database.I have to table Pc and Pc characteristics. They are related by Id. It's easy to add data in non realted table, but how can I add data in related table? What shoud I write in my Controller? There are some classes below.
Pc class:
#Entity
#Table(name = "pc")
public class Pc {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private int price;
public Pc(){}
public Pc(String name, int price) {
this.name = name;
this.price = price;
}
#OneToMany
#JoinColumn(name = "pc_id")
private List<PcChars> chars = new ArrayList<>();
public List<PcChars> getChars() {
return chars;
}
public void setChars(List<PcChars> chars) {
this.chars = chars;
}
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 int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
PcChars class:
#Entity
#Table(name = "pcChars")
public class PcChars {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String value;
public PcChars(){}
public PcChars(String name, String value) {
this.name = name;
this.value = value;
}
#ManyToOne
private Pc pc;
public Pc getPc() {
return pc;
}
public void setPc(Pc pc) {
this.pc = pc;
}
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 getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
PcCharactsController:
#Controller
public class PcCharactsController {
final private PcRepo pcRepo;
final private PcCharRepo pcCharRepo;
public PcCharactsController(PcRepo pcRepo, PcCharRepo pcCharRepo) {
this.pcRepo = pcRepo;
this.pcCharRepo = pcCharRepo;
}
//Pc characteristics list
#GetMapping("pc/{id}/")
public String pcCharList(#PathVariable int id, Model model) throws Exception{
Pc pc = pcRepo.findById(id).orElseThrow(() -> new Exception("PostId " +
id + " not found"));
List<PcChars> pcChars = pc.getChars();
model.addAttribute("model", pc.getName());
model.addAttribute("pcChars", pcChars);
return "charList";
}
//add characteristic
#PostMapping("pc/{id}/")
public String addCharact(){
return "charList";
}
Characteristics.ftl:
<html>
<head>
<title>Ho</title>
</head>
<body>
<div>
<form method="post" action="/pc/${id}/">
<input type="text" name="name">
<input type="text" value="value">
<input type="hidden" name="pc_id" value="${id}">
<button type="submit">Add</button>
</form>
</div>
</body>
</html>
Since you are not using any modelAttribute to bind the input values straight to a POJO you can use simple HttpServletRequest to get the input attributes, use them to create the object you want to store and store it using Hibernate
#PostMapping("pc/{id}/")
public String addCharact(HttpServletRequest req){
String name = req.getParameter("name");
String value = req.getParameter("value");
String id = req.getParameter("id");
PcChars pcchars = new PcChars(name,value,id); // create the corresponding constructor
SessionFactory sessionFactory;
Session session = sessionFactory.openSession();
Transaction tx = null;
try{
tx = session.getTransaction();
tx.begin();
session.save(pcchars);
tx.commit();
}
catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return "charList";
}
The part of Spring you're using is called Spring data, a library that allows you to use JPA in your Spring application. JPA is a specification for frameworks called ORM (Object-relationnal mapping).
To keep it simple, in your code, you do not use the relational approach anymore, but an object approach. Annotations you put on your classes' fields are used to define mappings between them and your database tables and fields.
So, you don't have to insert both entities separately anymore. You need to create a Pc instance, then to create a PcChars one, and finally to add the chars into the pc's chars list, like this :
Pc myPc = new Pc();
PcChars myChars = new PcChars();
myPc.getChars().add(myChars);
And when you'll use your repository to save the modifications with this :
pcRepo.save(myPc);
The JPA implementation will automatically do the work for you :
Inserting the row corresponding to your PC instance in the PC table
Inserting the row corresponding to your PC chars in the the PC_CHARS table
Settings the PC_CHARS.PC_ID with the ID of the freshly inserted PC instance's id in order to create the reference between them.
Not sure, but I think the ORM also do this when you add your chars to the pc instance :
myChars.setPc(myPc);
in order to make the bound between both instances reciprocal.
Note that I used arbitrary field names according to your schema.
I strongly suggest you to give responsibility of relationship to child side when using #OneToMany relation.
Modify your parent class as below:
#OneToMany(cascade = CascadeType.ALL, mappedBy="pc")
#BatchSize(size = 10)
private List<PcChars> chars = new ArrayList<>();
public void addPcChar(PcChar pcChar) {
this.chars.add(pcChar);
pcChar.setPc(this);
}
On the child class:
#ManyToOne
#JoinColumn(name = "pc_id")
private Pc pc;
Now you can persist your parent with child as below :
Pc pc = new Pc();
PcChar pcChar = new PcChar();
pc.addPcChar(pcChar);
If you use spring boot data repository, it saves it correctly as below
// assume your repository like below
public interface PcRepository extends CrudRepository<Pc, Integer> {}
// in your service or whatever in some place
pcRepository.save(pc);
With saving hibernate entity manager:
EntityManagerFactory emfactory =
Persistence.createEntityManagerFactory("Hibernate");
EntityManager entitymanager = emfactory.createEntityManager();
entitymanager.getTransaction().begin();
entitymanager.persist(pc);
entitymanager.getTransaction().commit();
entitymanager.close();
emfactory.close();
For detailed information about hibernate relationship take a look at my post : https://medium.com/#mstrYoda/hibernate-deep-dive-relations-lazy-loading-n-1-problem-common-mistakes-aff1fa390446
Related
I'm working with Spring, hibernate and MySql but I have some problem with seralization of query result.
First in my entity I added #JsonManagedReference on Set structure (#OneToMany side) and #JsonBackReference on single object reference (#ManyToOne side) and it works but I wasn't be able to retrieve all needed information (for example #ManyToOne reference).
So i swapping #JsonBackReference on set structure and #JsonManagedReference on single object but I retrieve
No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.model.tablesField.TableUI["data"]->java.util.ArrayList[0]->com.domain.Car["carType"]->com.domain.CarType_$$_jvst744_f["handler"])
I tried also with #JsonIgnore on Set structure but it doesn't work for the same issues.
This is my spring configuration
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
// properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
properties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
properties.put("hibernate.enable_lazy_load_no_trans",true);
return properties;
and this is part of one of my several entities:
/**
* Car generated by hbm2java
*/
#Entity
#Table(name = "car", catalog = "ATS")
public class Car implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer idCar;
#JsonManagedReference
private CarType carType;
#JsonManagedReference
private Fleet fleet;
private String id;
private int initialKm;
private String carChassis;
private String note;
#JsonBackReference
private Set<Acquisition> acquisitions = new HashSet<Acquisition>(0);
public Car() {
}
public Car(CarType carType, Fleet fleet, int initialKm, String carChassis) {
this.carType = carType;
this.fleet = fleet;
this.initialKm = initialKm;
this.carChassis = carChassis;
}
public Car(CarType carType, Fleet fleet, String id, int initialKm, String carChassis, String note,
Set<Acquisition> acquisitions) {
this.carType = carType;
this.fleet = fleet;
this.id = id;
this.initialKm = initialKm;
this.carChassis = carChassis;
this.note = note;
this.acquisitions = acquisitions;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id_car", unique = true, nullable = false)
public Integer getIdCar() {
return this.idCar;
}
public void setIdCar(Integer idCar) {
this.idCar = idCar;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_carType", nullable = false)
public CarType getCarType() {
return this.carType;
}
public void setCarType(CarType carType) {
this.carType = carType;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_fleet", nullable = false)
public Fleet getFleet() {
return this.fleet;
}
public void setFleet(Fleet fleet) {
this.fleet = fleet;
}
#Column(name = "id", length = 5)
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
#Column(name = "initialKm", nullable = false)
public int getInitialKm() {
return this.initialKm;
}
public void setInitialKm(int initialKm) {
this.initialKm = initialKm;
}
#Column(name = "carChassis", nullable = false, length = 20)
public String getCarChassis() {
return this.carChassis;
}
public void setCarChassis(String carChassis) {
this.carChassis = carChassis;
}
#Column(name = "note", length = 100)
public String getNote() {
return this.note;
}
public void setNote(String note) {
this.note = note;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "car")
public Set<Acquisition> getAcquisitions() {
return this.acquisitions;
}
public void setAcquisitions(Set<Acquisition> acquisitions) {
this.acquisitions = acquisitions;
}
}
one method that uses the query:
#Override
#RequestMapping(value = { "/cars/{idFleet}"}, method = RequestMethod.GET)
public #ResponseBody TableUI getCars(#PathVariable int idFleet) {
TableUI ajaxCall=new TableUI();
try {
ajaxCall.setData(fleetAndCarService.findCarsByIdFleet(idFleet));
return ajaxCall;
} catch (QueryException e) {
ErrorResponse errorResponse= ErrorResponseBuilder.buildErrorResponse(e);
LOG.error("Threw exception in FleetAndCarControllerImpl::addCar :" + errorResponse.getStacktrace());
return ajaxCall;
}
}
two class for the query:
public interface DefRdiRepository extends JpaRepository<DefRdi, Integer>{
//#Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM DefRdi c WHERE c.parName = ?1 AND c.description= ?2")
//Boolean existsByParNameAndDescription(String parName, String description);
//Query method of spring, I put findBy and then the key of research
DefRdi findByParNameAndDescription(String parName, String description);
}
public interface CarRepository extends JpaRepository<Car, Integer>, CarRepositoryCustom {
//Query method of spring, I put findBy and then the key of research
List<Car> findByFleetIdFleet(int idFleet);
}
Where is my error? I don't want Set object but only the single reference. The problem is only when I serialize. Thanks
UPDATE:
I use #JSonIgnore on all set collectionts and Eager instead lazy ad all works fine, but is there a way to retrieve all the information only when I want, for example having two different query?
So it doesn't work
#Override
#Transactional
public List<Car> findByFleetIdFleet(int idFleet) {
List<Car> carList= carRepository.findByFleetIdFleet(idFleet);
for (Car car:carList){
Hibernate.initialize(car.getCarType());
Hibernate.initialize(car.getFleet());
}
return carList;
// return carRepository.findByFleetIdFleet(idFleet);
}
All collections need to be fetched eagerly when loading them from data base, in order to get serialized by Spring. Make sure you fetch them eagerly (e.g. FetchMode.JOIN). You could also swap #JsonManagedReference from wanted fields with #JsonIgnore to black listed fields, Spring automatically serialises every field without annotation.
Update:
Changing the data repository to something like that should work, I am not sure it compiles, but I think you will get the point:
#EntityGraph(value = "some.entity.graph", type = EntityGraph.EntityGraphType.FETCH)
#Query(
value = "SELECT c FROM Car c INNER JOIN FETCH c.acquisitions WHERE c.id = :idFleet"
)
public interface CarRepository extends JpaRepository<Car, Integer>, CarRepositoryCustom {
//Query method of spring, I put findBy and then the key of research
List<Car> findByFleetIdFleet(int idFleet);
}
For more information look at this post and read the official documentation.
Workaround:
There seems to be a workaround, however fetching those collections eager like shown above should have a positive performance impact, since there is no need for loading proxies afterwards. Also no open transactions are needed at controller level.
Have to beans:
#Entity
#Table(name="book")
public class Book {
#Id
#Column(name="id_book")
#GeneratedValue(generator="increment")
#GenericGenerator(name="increment", strategy="increment")
private int id;
#Column
#Size(min=1,max=100)
private String title;
#Column
#Size(min=1,max=400)
private String description;
#Column
private Integer year=0;
#ManyToMany(cascade={CascadeType.ALL},fetch = FetchType.EAGER)
#Fetch (FetchMode.SELECT)
#JoinTable(name="book_author",
joinColumns={#JoinColumn(name="book_id_book")},
inverseJoinColumns= {#JoinColumn(name="author_id_author")})
private List<Author> author=new ArrayList<Author>();
//getters/setters
}
and:
#Entity
#Table(name="author")
public class Author {
#Id
#Column(name="id_author")
#GeneratedValue
private Integer id;
#Column
private String name;
#Column
private String surname;
#ManyToMany(mappedBy="author")
private Set<Book> book=new HashSet<Book>();
//getters/setters
}
In my jsp I'm have form for enter data about book, and multiple list for select author(s) from DB, problem only in select authors, therefore give only this code:
<sf:select multiple="true" path="author" items="${authors}" size="7" >
</sf:select>
Where ${authors} - List with objects Author from DB. Use POST request.
In my controller for this page have this (I know it's not correct):
#RequestMapping(value="/addbook", method=RequestMethod.POST)
public String addBook(Book book){
hibarnateService.saveBook(book);
return "redirect:/books";
}
When I'm create book without select authors, but enter another information, all fine, book save in DB. When select some authors get this - The request sent by the client was syntactically incorrect.
Problem solved by add in controller:
#InitBinder
protected void initBinder(WebDataBinder binder){
binder.registerCustomEditor(Author.class, new Editor(hibarnateService));
}
and create class:
public class Editor extends PropertyEditorSupport {
private final Dao hibernateService;
public Editor(Dao hibernateService){
this.hibernateService=hibernateService;
}
#Override
public void setAsText(String text) throws IllegalArgumentException{
Author author=hibernateService.getAuthor(Integer.parseInt(text));
setValue(author);
}
}
P.S. What wrong with me? I can't find the right answer myself until I ask here)
You will need to implement initBinder in your controller, below can be tentative code (not tested)
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(List.class, "authors ", new CustomCollectionEditor(List.class)
{
#Override
protected Object convertElement(Object element)
{
Long id = null;
if(element instanceof Long) {
//From the database 'element' will be a Long
id = (Long) element;
}
return id != null ? authorService.loadAuthorById(id) : null;
}
});
}
I have configured the OneToMany mappings for my tables.So when inserting values to the fisrt table on second time it gives me an error Cannot insert duplicate key row in object. Here is my tables.
Table -1 (feature_id is pk and auto generated by table) and name is inserting by me.
Feature_id(PK)
Name
feature table has index
"GO
CREATE UNIQUE INDEX idx_Name ON "dbo"."Feature"(Name)
Table-2 (Feature_Version_id PK and auto generated by table)
Feature_Version_id ,
Version_Name
Feature_id
POJO classes are :
#Entity
#Table(name="FEATURE")
public class Feature {
private int feature_id;
private String name;
private Set<FeatureVersion> featureversion = new HashSet<FeatureVersion>(0);
public Feature() {
}
public Feature(String name ,Set<FeatureVersion> featureversion) {
this.name = name;
this.featureversion = featureversion;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="FEATURE_ID")
public int getFeature_id() {
return feature_id;
}
public void setFeature_id(int feature_id) {
this.feature_id = feature_id;
}
#Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch=FetchType.LAZY,mappedBy="feature")
public Set<FeatureVersion> getFeatureversion() {
return featureversion;
}
public void setFeatureversion(Set<FeatureVersion> featureversion) {
this.featureversion = featureversion;
}
}
Second table POJO class:
#Entity
#Table(name="FEATURE_VERSION")
public class FeatureVersion {
private int feature_version_id;
private String version_name;
private int feature_id;
private Feature feature;
private Set<PartFeatureVersion> partfeatureversion = new HashSet<PartFeatureVersion>(0);
public FeatureVersion() {
}
public FeatureVersion(Feature feature, String version_name, int feature_id) {
this.feature = feature;
this.version_name = version_name;
this.feature_id = feature_id;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="FEATURE_VERSION_ID")
public int getFeature_version_id() {
return feature_version_id;
}
public void setFeature_version_id(int feature_version_id) {
this.feature_version_id = feature_version_id;
}
#Column(name="VERSION_NAME")
public String getVersion_name() {
return version_name;
}
public void setVersion_name(String version_name) {
this.version_name = version_name;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="feature_id")
public Feature getFeature() {
return feature;
}
public void setFeature(Feature feature) {
this.feature = feature;
}
#OneToMany(fetch=FetchType.LAZY,mappedBy="featureversion")
public Set<PartFeatureVersion> getPartfeatureversion() {
return partfeatureversion;
}
public void setPartfeatureversion(Set<PartFeatureVersion> partfeatureversion) {
this.partfeatureversion = partfeatureversion;
}
}
Main class :
Session session = (Session) HibernateUtil.getSessionFactory().openSession();
Feature feature = new Feature();
FeatureVersion featurever = new FeatureVersion();
feature.setName("stack");
session.save(feature);
featurever.setVersion_name("12.2");
featurever.setFeature(feature);
feature.getFeatureversion().add(featurever);
session.save(featurever);
session.getTransaction().commit();
session.flush();
Here is my input values :
(feature id generated by table)
First attempt for first table: stack
First attempt for second table : 12.2
(feature_id come from feature table)
second attempt for first table: stack
second attempt for second table : 12.3
OneToMany configuration will take care if more than one values come to OneToMany releationship ? Or i need to check if value is exist then just the version name ? These all values loop through from the list. Please advise what should i do here .
Thanks,
I need to use raw SQL within a Spring Data Repository, is this possible? Everything I see around #Query is always entity based.
The #Query annotation allows to execute native queries by setting the nativeQuery flag to true.
Quote from Spring Data JPA reference docs.
Also, see this section on how to do it with a named native query.
YES, You can do this in bellow ways:
1. By CrudRepository (Projection)
Spring Data Repositories usually return the domain model when using query methods. However, sometimes, you may need to alter the view of that model for various reasons.
Suppose your entity is like this :
import javax.persistence.*;
import java.math.BigDecimal;
#Entity
#Table(name = "USER_INFO_TEST")
public class UserInfoTest {
private int id;
private String name;
private String rollNo;
public UserInfoTest() {
}
public UserInfoTest(int id, String name) {
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", nullable = false, precision = 0)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "name", nullable = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Basic
#Column(name = "roll_no", nullable = true)
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
Now your Projection class is like below. It can those fields that you needed.
public interface IUserProjection {
int getId();
String getName();
String getRollNo();
}
And Your Data Access Object(Dao) is like bellow :
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.ArrayList;
public interface UserInfoTestDao extends CrudRepository<UserInfoTest,Integer> {
#Query(value = "select id,name,roll_no from USER_INFO_TEST where rollNo = ?1", nativeQuery = true)
ArrayList<IUserProjection> findUserUsingRollNo(String rollNo);
}
Now ArrayList<IUserProjection> findUserUsingRollNo(String rollNo) will give you the list of user.
2. Using EntityManager
Suppose your query is "select id,name from users where roll_no = 1001".
Here query will return an object with id and name column. Your Response class is like bellow:
Your Response class is like this:
public class UserObject{
int id;
String name;
String rollNo;
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
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 getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
here UserObject constructor will get an Object Array and set data with the object.
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
Your query executing function is like bellow :
public UserObject getUserByRoll(EntityManager entityManager,String rollNo) {
String queryStr = "select id,name from users where roll_no = ?1";
try {
Query query = entityManager.createNativeQuery(queryStr);
query.setParameter(1, rollNo);
return new UserObject((Object[]) query.getSingleResult());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
Here you have to import bellow packages:
import javax.persistence.Query;
import javax.persistence.EntityManager;
Now your main class, you have to call this function. First get EntityManager and call this getUserByRoll(EntityManager entityManager,String rollNo) function. The calling procedure is given below:
Here is the Imports
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
get EntityManager from this way:
#PersistenceContext
private EntityManager entityManager;
UserObject userObject = getUserByRoll(entityManager,"1001");
Now you have data in this userObject.
Note:
query.getSingleResult() return a object array. You have to maintain the column position and data type with the query column position.
select id,name from users where roll_no = 1001
query return a array and it's [0] --> id and [1] -> name.
More info visit this thread and this Thread
Thanks :)
It is possible to use raw query within a Spring Repository.
#Query(value = "SELECT A.IS_MUTUAL_AID FROM planex AS A
INNER JOIN planex_rel AS B ON A.PLANEX_ID=B.PLANEX_ID
WHERE B.GOOD_ID = :goodId",nativeQuery = true)
Boolean mutualAidFlag(#Param("goodId")Integer goodId);
we can use createNativeQuery("Here Native SQL Query ");
for Example :
Query q = em.createNativeQuery("SELECT a.firstname, a.lastname FROM Author a");
List<Object[]> authors = q.getResultList();
This is how you can use in simple form
#RestController
public class PlaceAPIController {
#Autowired
private EntityManager entityManager;
#RequestMapping(value = "/api/places", method = RequestMethod.GET)
public List<Place> getPlaces() {
List<Place> results = entityManager.createNativeQuery("SELECT * FROM places p limit 10").getResultList();
return results;
}
}
It is also possible to use Spring Data JDBC, which is a fully supported Spring project built on top of Spring Data Commons to access to databases with raw SQL, without using JPA.
It is less powerful than Spring Data JPA, but if you want lightweight solution for simple projects without using a an ORM like Hibernate, that a solution worth to try.
I am developing application using Spring and Hibernate with MySQL. I am new to Hibernate and did basic tasks...
Now I need to apply joins in select query to get data from multiple table using annotations. I have searched for it but still I didn't get any idea...
Here my database tables and bean classes :
Table 1: 'employee_info' ( id, empid, empname, doj and jobtitle )
Table 2: 'employee_login' ( username, password, status and empid )
And my bean classes are:
EmployeeInfoForm.java
#Entity()
#Table(name = "employee_info")
public class EmployeeInfoForm {
#Id
#GeneratedValue
#Column(name = "id", unique = true, nullable = true)
private int id;
#Column(name = "empId")
private int empId;
#Column(name = "empname")
private String empName;
#Column(name = "doj")
private Date empDoj;
#Column(name = "jobtitle")
private String empJobTitle;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public void setEmpDoj(Date empDoj) {
this.empDoj = empDoj;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Date getEmpDoj() {
return empDoj;
}
public void setEmp_Doj(Date empDoj) {
this.empDoj = empDoj;
}
public String getEmpJobTitle() {
return empJobTitle;
}
public void setEmpJobTitle(String empJobTitle) {
this.empJobTitle = empJobTitle;
}
}
EmployeeLoginForm.java
#Entity()
#Table(name = "employee_login")
public class EmployeeLoginForm {
#Id
#Column(name = "username")
private String empUserName;
#Column(name = "password")
private String empPassword;
#Column(name = "status")
private String empStatus;
#Column(name = "empid")
private int empId;
public String getEmpUserName() {
return empUserName;
}
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public void setEmpUserName(String empUserName) {
this.empUserName = empUserName;
}
public String getEmpPassword() {
return empPassword;
}
public void setEmpPassword(String empPassword) {
this.empPassword = empPassword;
}
public String getEmpStatus() {
return empStatus;
}
public void setEmpStatus(String empStatus) {
this.empStatus = empStatus;
}
}
Requirement:
I want to select fields empid, empname, jobtitle from employee_info and field status from employee_login table when the empid matches on both table...
Please help me to complete my work...
Any suggestions and guidance are appreciated...
There is an association between EmployeeInfoForm and EmployeeLoginForm that I am not seeing in your code. Maybe there is an Employee class there? If that is the case then you need to add that. So let us assume that each employee has many forms. Then you will code the Employee side of the relationship like this:
public class Employee{
#OneToMany(cascade = CascadeType.ALL, mappedBy = "employee")
private Set<EmployeeLoginForm> loginForms = new HashSet<EmployeeLoginForm>();
...
}
And the Many side of the relationship in the EmployeeLoginForm class:
#ManyToOne
Employee employee;
This will create the table structure such that:
emploee = (id, etc ...)
employeelogin = (id, employee, ....)
Now, any time you need a list of the Logins of an Employee you get it from the Employee object without needing a Query.
Set<EmployeeLoginForm> logins = e.getLoginForms(); //where e is an employee object.
If you did want to query you can do
select o from EmployeeLoginForm o join o.employee
But that is unnecessary in this case.
You are thinking in database / pure SQL terms when you talk about performing joins with select statements. The power (and danger) of Hibernate is that it abstracts this away from you and lets you think in Object terms. What you need is a relationship between the 2 objects and then let Hibernate handle this relationship.
I recommend you spend some time reading this:
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/associations.html
to get a better understanding of how Hibernate can help.
You can do the following using the Hibernate criteria projection:
public List extractEmployeeAttributes() {
log.debug("extractEmployeeAttributes");
try {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Criteria c1 = session.createCriteria(employee_info.class,emp_info);
Criteria c2 = session.createCriteria(employee_login.class,emp_log);
c1.setProjection(Projections.projectionList()
.add(Projections.property("empid"))
.add(Projections.property("empname"))
.add(Projections.property("jobtitle"))
.add(Projections.property("employee_info "))
.add(Restrictions.and(Property.eqName(emp_info.empId,emp_log.empId))
return c1.list();
} catch (RuntimeException re) {
log.error("extractEmployeeAttributes failed", re);
throw re;
}
}