I am practice Hibernate with the following classes and a MySQL database.
#Entity
#Table(name="Student")
public class Student {
#Id
#GeneratedValue
private int student_id;
private String student_name;
#ManyToOne(cascade=CascadeType.ALL)
private StudentAddress address;
#Transient
#Temporal(TemporalType.DATE)
private Date birthDay;
public Student() {
}
public Date getBirthDay() {
return birthDay;
}
public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}
public int getStudent_id() {
return student_id;
}
public void setStudent_id(int rollNo) {
this.student_id = rollNo;
}
public String getStudent_name() {
return student_name;
}
public void setStudent_name(String name) {
this.student_name = name;
}
public StudentAddress getAddress() {
return address;
}
public void setAddress(StudentAddress address) {
this.address = address;
}
}
#Entity
#Table(name="student_address")
public class StudentAddress {
#Id
#GeneratedValue
private int address_id;
private String address_detail;
public int getAddress_id() {
return address_id;
}
public void setAddress_id(int address_id) {
this.address_id = address_id;
}
public String getAddress_detail() {
return address_detail;
}
public void setAddress_detail(String address_detail) {
this.address_detail = address_detail;
}
}
I keep getting the following error message from these sql statements:
Hibernate: insert into student_address (address_detail) values (?)
Hibernate: insert into Student (address_address_id, student_name) values (?, ?)
Error Message:
Unknown column '**address_address_id'** in 'field list'
My database has the field name address_id.
Hibernate keeps appending address to address_id and changes the column name. I could probably change the field name from address to address_address_id in my database but what is causing this to happen. Is it a valid behavior in Hibernate and can I change it?
That's the default column name Hibernate uses for #ManyToOne association:
Default (only applies if a single join column is used): The
concatenation of the following: the name of the referencing
relationship property or field of the referencing entity or embeddable
class; "_"; the name of the referenced primary key column. If there is
no such referencing relationship property or field in the entity, or
if the join is for an element collection, the join column name is
formed as the concatenation of the following: the name of the entity;
"_"; the name of the referenced primary key column.
To specify the desired column name:
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="address")
private StudentAddress address;
Related
please help me with this one. I have a very simple crud project with a student table in oracle DB(ID,name,age,email) in springboot and all i want to know is get a student with a method in the jpa repository that calls a stored procedured. when run the project i got an error PLS-00221 is not a procedure or is undefined.
--stored procedure
CREATE OR REPLACE FUNCTION
findstudentbyid
RETURN STUDENT%ROWTYPE
IS
estudiante STUDENT%ROWTYPE;
BEGIN
SELECT *
INTO estudiante
FROM STUDENT
WHERE ID=1;
RETURN estudiante;
END findstudentbyid;
//Entity in sprongboot project
#Entity
#Table
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(
name = "findstudentbyid",
procedureName = "findstudentbyid"
)
})
public class Student {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
//Private variables
private Long ID;
private String name;
private Number age;
private String email;
//Constructor
protected Student(){}
public Student(String name , Number age , String email){
this.name = name;
this.age = age;
this.email = email;
}
public Long getID() {
return ID;
}
public String getName() {
return name;
}
public Number getAge() {
return age;
}
public String getEmail() {
return email;
}
}
//JPA CRUD REPOSITORY
public interface StudentRepository extends CrudRepository<Student,Long>{
#Procedure(name = "findstudentbyid")
Iterable<Student> findstudentbyid();
}
You create a function but not a stored procedure.
These objects are different for DB and JPA, try to change your create function to create procedure or change the procedure's call to the function's call signature.
Also, see here for more info about JPA and function call.
**This is student pojo class**
#Entity
#Table(name="student")
public class Student {
#Id
private int studentId;
private String StudentName;
#Embedded
private Adress add;
#Embedded
private Adress temp;
public void setTemp(Adress temp) {
this.temp = temp;
}
public void setAdd(Adress add) {
this.add = add;
}
public void setStudentId(int studentId) {
this.studentId = studentId;
}
public void setStudentName(String studentName) {
StudentName = studentName;
}}
** this is Address pojo class**
#Embeddable
public class Adress {
#Column(name="village" )
private String village;
#Column(name="pin")
private int pin;
public void setVillage(String village) {
this.village = village;
}
public void setPin(int pin) {
this.pin = pin;
}}
** Main class **
public class Test {
public static void main(String[] args) {
SessionFactory factory=Sessionfactory.getfactory();
Session session=factory.openSession();
Adress a=new Adress();
a.setPin(123);
a.setVillage("kanipakam");
Adress a2=new Adress();
a2.setVillage("kanchi");
a2.setPin(1234);
Student s=new Student();
s.setAdd(a);
s.setTemp(a2);
s.setStudentId(101);
s.setStudentName("uday");
Transaction tx=session.beginTransaction();
session.save(s);
tx.commit();
System.out.println("object saved");
session.close();
factory.close();
}}
** showing error**
while running this code its show below error please help me
Exception in thread "main" org.hibernate.MappingException: Repeated column in mapping for entity: com.sathya.pojo.Student column: pin (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:709)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:731)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:727)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:753)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:506)
at org.hibernate.mapping.RootClass.validate(RootClass.java:270)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1358)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1849)
at com.sathya.singleton.Sessionfactory.getfactory(Sessionfactory.java:21)
at com.sathya.Test.Test.main(Test.java:16)
#Embedded annotation specifies that fields from the object are persisted in the same table as root entity. The names for the columns are taken from the #Embeddable configuration. So in your case
#Embedded
private Adress add;
#Embedded
private Adress temp;
Specifies that there are 2 objects of type Adress on your #Entity. The problem is that gived your current configuration add.village and temp.village both will be mapped to village column of student table.
You have 2 options to resolve the issue:
Override mappings for one (or both) #Embedded properties and specify different columns like described here
Use many-to-one or one-to-one relation to address and store address records in a separate database table.
For fail safe am always using double quotes in my mapping class. And this only for PostgreSQL
Here is my class:
#Entity
#Table(name="`Person`"
,schema="public"
)
public class Person implements java.io.Serializable {
private Integer id;
private String name;
private String address;
public Person() {
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="`ID`", nullable=false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name="`Name`")
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name="`Address`")
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
}
When am trying insert using Am getting below exception:
org.postgresql.util.PSQLException: The column nameIDwas not found in this ResultSet.
Query it ran for insert was:
insert into public."Person" ("Address", "Name") values (?, ?)
I can't remove double quotes for other reasons.
Please help me to get this problem fixed.
Update:
Database Schema:
CREATE TABLE "Person"
(
"ID" INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('"Person_ID_seq"'::regclass),
"Name" VARCHAR(255),
"Address" VARCHAR(255)
);
If everything need to be quoted, add the following flags to hibernate.properties or persistence.xml file
hibernate.globally_quoted_identifiers=true
and remove all the single quote from the class Person. However, take note that for Postgresql, placing table/column name etc in double quote effectively turn them into case sensitives. So the case for the table/column in the database must be exact match of the corresponding name in the #Table and #Column annotation.
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 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;
}
}