I have a Student table with Columns name, age, gender and address.
Is it possible to create a Java POJO class with #Entity annotation and
have only name and address in it?
#Entity
#Table(name="Student")
public class Student {
#Column(name = "name")
String name;
#Column(name="address")
String address;
}
I am new to Spring boot and searched a bit around this but couldn't get any specific answer.
Related
I use spring jpa+hibernate to connect to an Oracle DB with 2 tables: Customers and LegacyCustomers.
Customers extends LegacyCustomers by adding some additional columns.
#Entity
#Table(name="Customers")
public class Customers extends LegacyCustomers {
#Column(name="NewId") private String newId;
#Column(name="PhoneNumber") private String phoneNumber;
}
#Entity
#Table(name="LegacyCustomers")
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class LegacyCustomers {
#Column(name="OldId") private String oldId;
#Column(name="Name") private String name;
#Column(name="Address") private String address;
}
However they are completely different tables. I am looking for a way to express the relationship in java but avoid the polymorphism that hibernate creates when querying the superclass table (LegacyCustomers). How can I tell hibernate to use only columns from the superclass when I query for LegacyCustomers?
Unfortunately the #Polymorphism annotation suggested here doesnt help.
Thanks for the help
To achieve your goal, you need to use the #MappedSuperclass annotation instead to a new BaseCustomers class that encapsulates the common properties:
#MappedSuperclass
public class BaseCustomers {
#Column(name="OldId") private String oldId;
#Column(name="Name") private String name;
#Column(name="Address") private String address;
}
Afterward, the LegacyCustomers just extend the BaseCustomers and only adds the #Entity annotation since the BaseCustomers is not treated as an entity:
#Entity
#Table(name="LegacyCustomers")
public class LegacyCustomers extends BaseCustomers {
}
And the Customers entity does the same:
#Entity
#Table(name="Customers")
public class Customers extends BaseCustomers {
#Column(name="NewId") private String newId;
#Column(name="PhoneNumber") private String phoneNumber;
}
That's it.
I am pretty new to Hibernate and I am studying it on a tutorial. I have some problems understanding how exactly the OneToMany annotation works.
So I have these 2 entity classes: Student that represents a student and Guide that represents a person that guides the student. So each student is associated with a single guide but a single guide can follow more that one student. I want a guide to know the students associated to him.
So I have:
Student:
#Entity
public class Student {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name="enrollment_id", nullable=false)
private String enrollmentId;
private String name;
#ManyToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
#JoinColumn(name="guide_id")
private Guide guide;
public Student() {}
public Student(String enrollmentId, String name, Guide guide) {
this.enrollmentId = enrollmentId;
this.name = name;
this.guide = guide;
}
public Guide getGuide() {
return guide;
}
public void setGuide(Guide guide) {
this.guide = guide;
}
}
So the #ManyToOne annotation on the guide field:
#ManyToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
#JoinColumn(name="guide_id")
private Guide guide;
means that a single guide is associated a single student but a guide can follow many students. Is it right? What exactly does the specified cascade settings do? I think it means that when I persist a Student object that contains a Guide object as field also this Guide object is also automatically persisted. And the same thing happens when I remove a Student object, the related Guide record is deleted...but I am not absolutely sure about it...
Ok, doing it this way I will have a mono directional relationship between a record in the Student table and a record in the Guide table because in the Student table I will have a foreign key to join the Guide table so the student can know its guide but, doing it this way, the guide can not know the followed student...and this is not smart.
To do it the Guide class is implemented in this way:
#Entity
public class Guide {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name="staff_id", nullable=false)
private String staffId;
private String name;
private Integer salary;
#OneToMany(mappedBy="guide", cascade={CascadeType.PERSIST})
private Set<Student> students = new HashSet<Student>();
public Guide() {}
public Guide(String staffId, String name, Integer salary) {
this.staffId = staffId;
this.name = name;
this.salary = salary;
}
public Set<Student> getStudents() {
return students;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
public void addStudent(Student student) {
students.add(student);
student.setGuide(this);
}
}
So, as you can see, this class contains:
#OneToMany(mappedBy="guide", cascade={CascadeType.PERSIST})
private Set<Student> students = new HashSet<Student>();
that it is used to declare the bidirectional relationship.
So it seems to me that this annotation automatically create a guide_id field into the Student table that represent the foreign key that implement the bidirectional relation.
In fact using this mapping the Student table is automatically created in this way in my database:
'id', 'bigint(20)', 'NO', 'PRI', NULL, 'auto_increment'
'enrollment_id', 'varchar(255)', 'NO', '', NULL, ''
'name', 'varchar(255)', 'YES', '', NULL, ''
'guide_id', 'bigint(20)', 'YES', 'MUL', NULL, ''
So in the Student entity class I have not defined the guide_id field but I have it in the Student table on the database. So I think that the creation of this field in the table depends on the previous #OneToMany annotation defined in the Guide entity class. Is that correct or am I missing something?
Yes, you can define a #OneToMany entity without a bidirectional association, and the added column is on the Many entity side in the database (even though the entity doesn't know it is linked to the One-side entity).
You can also use a join table for this, but it's not necessary.
I am studying for the Spring Core certification and I have some doubts about how works the Embeddables JPA class.
So I have this example:
1) A Customer entity class that map the T_CUSTOMER DB table
#Entity
#Table(name= “T_CUSTOMER”)
public class Customer {
#Id
#Column (name=“cust_id”)
private Long id;
#Embedded
#AttributeOverride
(name="postcode", column=#Column(name="ZIP"))
private Address office;
…
…
…
}
2) An Address entity class that simply represent an address (and that not map any DB table):
#Embeddable
public class Address {
private String street;
private String suburb;
private String city;
private String postcode;
private String country;
}
As you can see in the Customer entity class there is this field:
#Embedded
#AttributeOverride
(name="postcode", column=#Column(name="ZIP"))
private Address office;
What exactly are the rules and the meaning of the #Embedded and #AttributeOverride annotations?
I think that this works in the following way:
1) Some column of the T_CUSTOMER DB table are mapped not directly into the Customer entity class but are mapped and stored into the field of the Address class that is a field of the the Customer class.
2) The table column named ZIP is mapped with the postcode property of the Address class.
Is it right or am I missing something?
Tnx
I want to use one class to map three tables. I know javax.persistance provides the #SecondaryTable annotation to map two tables to one class.
Below is the code, where I have used #SecondaryTable. It allows me to define only one secondary table. But I need 3 tables to be used by the same class.
#Entity
#Table(name = "table1")
#SecondaryTable(name="table2")
public class TableConfig
implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "mac", table= "table1")
private String uniqueIdentifier;
I want to use one class to map three tables, From what I know is that javax.persistance provides #SecondaryTable annotation to map two tables to one class
use #SecondaryTables to map more than one table.
You can map a single entity bean to several tables using the #SecondaryTables class level annotations. To express that a column is in a particular table, use the table parameter of #Column or #JoinColumn.
for example there is 3 entity's namely: Name , Address & Student:
Name entity will look like:
#Entity
#Table(name="name")
public class Name implements Serializable {
#Id
#Column(name="id")
private int id;
#Column(name="name")
private String name;
public Name(){}
public Name(int id,String name){
this.id=id;
this.name=name;
}
//getters and setters
}
Address entity will look like:
#Entity
#Table(name="address")
public class Address implements Serializable {
#Id
#Column(name="id")
private int id;
#Column(name="address")
private String address;
public Address(){}
public Address(int id, String address) {
super();
this.id = id;
this.address = address;
}
//getters and setters
}
Student entity will look like:
#Entity
#Table(name="student")
#SecondaryTables({
#SecondaryTable(name="name", pkJoinColumns={
#PrimaryKeyJoinColumn(name="id", referencedColumnName="student_id") }),
#SecondaryTable(name="address", pkJoinColumns={
#PrimaryKeyJoinColumn(name="id", referencedColumnName="student_id") })
})
public class Student implements Serializable {
#Id
#Column(name="student_id")
private int studentId;
#Column(table="name")
private String name;
#Column(table="address")
private String address;
public Student(){}
public Student(int studentId){
this.studentId=studentId;
}
//getters and setters
}
Store like:
Student s= new Student(1);
session.save(s);
Name n=new Name(s.getStudentId(),"Bilal Hasan");
session.save(n);
Address address = new Address(s.getStudentId(), "India");
session.save(address);
Student ob = (Student)session.get(Student.class, s.getStudentId());
System.out.println(ob.getStudentId());
System.out.println(ob.getName());
System.out.println(ob.getAddress());
ouput:
1
Bilal Hasan
India
you can define one class like below :
#Entity
#Table(name="table1")
#SecondaryTables({
#SecondaryTable(name="table2", pkColumnJoins={#PrimaryKeyJoinColumn(name = "id")}),
#SecondaryTable(name="table3", pkColumnJoins={#PrimaryKeyJoinColumn(name = "id")})
})
public class TestEntity {
#Id
#GeneratedValue
private int id;
private String field1;
#Column(name="column2", table="table2")
private String field2;
#Column(name="column3", table="table3")
private String field3;
getter and setter...
}
In your DB, should has three table, and all of them should has the same primary key "id".
then, use can test like this:
TestEntity test = new TestEntity();
test.setField1("field1");
test.setField2("field2");
test.setField3("field3");
em.merge(test);
after test, in your DB, you will find one record in each table:
table1:
1, field1
table2:
1, field2
table3:
1, field3
all of them will share the primary key value. Hope this will help you.
In Hibernate mapping file you can specify the entity-name mapping with virtual name along with polymorphism="explicit" and class name would be physical class name. Like that you may do multiple mappings. While loading the object use entityname (virtual name).
is there a simple way to persist some of the fields in another class and table using hibernate.
For example, I have a Person class with name, surname, email, address1, address2, city, country fields. I want my classes to be:
public class Person
{
private String name;
private String surname;
private String email;
private Address address;
// ..
}
public class Address
{
private Person person; // to whom this belongs
private String address1;
private String address2;
private String city;
private String country;
// ..
}
and I want to store Address in another table. What is the best way to achieve this?
Edit: I am using annotations. It does not have to be the way I described, I am looking for best practices.
Edit 2: What will be the Id of Address?
PS. If there is a way to make Address immutable (to use as a value object) that is even better, or maybe not because I thought everything from wrong perspective :)
map Address as an entity and add a primary key (an auto-generated id)
map the relation between Person and Address as one-to-one (#OneToOne on each field)
With Hibernate 3.5 it is possible to define foreign generators (aka. JPA mapping), details are here.
It is pretty straight forward Person should implement Serializable then #Id annotation is added to person.
#Entity
#AccessType(value = "field")
#Table(name = "addresses")
public class Address
{
#Id
#OneToOne
#JoinColumn(name = "person_id")
private Person person;
// ...
}
There is an alternative but I really like the first one:
#Entity
#AccessType(value = "field")
#Table(name = "addresses")
public class Address
{
#Id
private int personId;
#MapsId
#OneToOne
#JoinColumn(name = "person_id")
private Person person;
// ...
}