Hibernate : for a single table group attributes into a subclass - java

I want to do :
create table user (
id bigint primary key auto_increment,
firstname varchar(128),
lastname varchar(128),
street varchar(128),
zipcode mediumint,
city varchar(128)
)
then :
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstname;
private String lastname;
private Address address; // Here I want an Address rather than street, zip, and city directly inside User
...
}
and :
public class Address {
private String street;
private Integer zipcode;
private String city;
...
}
(that is an example)
How to do that with Hibernate ? #OneToOne ? The problem seems simple and since I can't find the solution around here, it must be obvious.

First, annotate your Address class with #Embeddable:
#Embeddable
public class Address {
/*class definition here*/
...
}
And then update your user class in this way:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstname;
private String lastname;
#Embedded
private Address address;
...
}
That's it. If you want a more complex example look here. Just pay attention to model classes definition, it makes no difference if you are using Spring Boot or not as long as you handle your database with JPA.

You can associate entities through a one-to-one relationship using #OneToOne annotation.
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Address address;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
public Address getAddress()
{
return address;
}
}
Reference:
https://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping-association

Related

many entities one table hibernate

I work with mySQL, hibernate and Spring Datas and I want to link a table with more than one entity.
The table looks like this but more complex (with many-to-one relations...) :
CREATE TABLE FOOBAR (
id BIGINTEGER NOT NULL AUTO_INCREMENT,
type ENUM('FOO', 'BAR'),
name VARCHAR(30),
foo_style ENUM('ONE', 'TWO')),
PRIMARY KEY(id);
The entities that I want to create. I want a generic table that cans recover all the entries, and two tables that cans recover only the rows corresponding to the correct enum :
#Table
public class FooBar {
#Id
#Column
private String id;
#Column
#Enumerated(EnumType.STRING)
private Type type;
#Column
private String name;
#Column
#Enumerated(EnumType.STRING)
private FooStyle fooStyle;
}
#Table //On type foo
public class Foo {
#Id
#Column
private String id;
#Column
private String name;
#Column
#Enumerated(EnumType.STRING)
private FooStyle fooStyle;
}
#Table //On type bar
public class Bar {
#Id
#Column
private String id;
#Column
private String name;
}
Thanks in advance !

One-to-One association with composite ID of owner Entity

I have a to make a one-to-one association between two Entities, but one of them must have two #Id. One is PRI another one is MUL. How must i declare composite id, and how do i need to map the classes?
#Entity
#Table(name = "PERSONS")
public class Person implements Serializable{
private static final long serialVersionUID = -3451407520028311143L;
#Id
#Column(name = "ID")
private Integer id;
#Column(name = "ADDRESS_ID")
private Integer addressId;
#Column(name ="NAME")
private String name;
#OneToOne(mappedBy= "person", cascade= CascadeType.ALL)
private Address address;
...
}
second class is mapped via #IdClass annotation
#Entity
#Table ( name = "ADDRESS" )
#IdClass(AddressKeys.class)
public class Address implements Serializable {
#Id
#Column ( name = "ID")
private Integer id;
#Id
#Column ( name = "PERSON_ID")
private Integer idPerson;
#Column ( name = "CITY" )
private String city;
#OneToOne(cascade= CascadeType.ALL)
#JoinColumn(name="PERSON_ID")
private Person person;
...
}
and the id class
class AddressKeys implements Serializable{
private Integer id;
private Integer idPerson;
//getters and setters
#Override
public int hashCode() {
...
return result;
}
#Override
public boolean equals(Object obj) {
...
}
}
So when i try to create and save a record i have a next error
Could not open sessionRepeated column in mapping for entity:
hibernateMappedModels.base1.mappedClasses.oneToOne.Address column:
PERSON_ID (should be mapped with insert="false" update="false")
java.lang.NullPointerException at
hibernateMappedModels.base1.Main.run(Main.java:45) at
hibernateMappedModels.base1.Main.main(Main.java:24
I tryed to make an Id fields unInsertable and unUpdatable, and it was working, but i need them to be insertable and updatable; Is there any possibility to do it?
I am confused by your mappings and not sure what is required other then the simple mappings below: if I am missing something then you will need to expand on your question. You are getting the error as you have mapped the column twice - once via the one-to-one and once as a simple property. Additionally, I am not sure why you require a composite key on address.
#Entity
#Table(name = "PERSONS")
public class Person implements Serializable{
private static final long serialVersionUID = -3451407520028311143L;
#Id
#Column(name = "ID")
private Integer id;
#Column(name ="NAME")
private String name;
#OneToOne(mappedBy= "person", cascade= CascadeType.ALL)
private Address address;
}
#Entity
#Table ( name = "ADDRESS" )
public class Address implements Serializable {
#Id
#Column ( name = "ID")
private Integer id;
#Column ( name = "CITY" )
private String city;
#OneToOne(cascade= CascadeType.ALL)
#JoinColumn(name="PERSON_ID")
private Person person;
}

#OneToOne Hibernate with annotations. Can't properly save

I can't make my foreign keys auto generate using hibernate and jpa with annotations. Everything seems ok, The entries are saved in database. All the date come from one form which, when submited creates an User object with ModelAttribute and then saves it in Database.
Here are my beans. Anything else i should add ?
#Entity
#Table(name="adress")
public class Adress implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="adress_id")
private Integer adressId;
#NotBlank(message="The city must be completed")
#Column(name="city")
#Size(min=5,max=30)
private String city;
#NotBlank(message="The street must be completed")
#Column(name="street")
#Size(min=5,max=30)
private String street;
#NotNull(message="The street number must be completed")
#NumberFormat
#Column(name="street_no")
private Integer streetNo;
#OneToOne
#JoinColumn(name="user_id")
private User user;}
and the other one:
#Entity
#Table(name="users")
public class User implements Serializable {
#Id
#Column(name="user_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer userId;
#NotBlank(message="Username can't be blank")
#Size(min=5,max=30)
#Column(name="username")
private String username;
#NotBlank(message="Password field can't be blank")
#Size(min=5,max=30)
#Column(name="password")
private String password;
#NumberFormat
#NotNull(message="Age field must not be blank")
#Column(name="age")
private Integer age;
#Column(name="message")
#Size(min=0,max=100)
private String message;
#Column(name="date")
#DateTimeFormat(pattern="dd/mm/yyyy")
private Date dateCreated;
#OneToOne(mappedBy="user",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
private Adress adress;
+getters and setters for them
public void save(T entity){
sessionFactory.getCurrentSession().save(entity);
}
If I understand you correctly and you're trying to get Hibernate to set the foreign key on your related record this might help. Try getting rid of mappedBy and instead specify the JoinColumn. This works for me on a one to many:
The order:
#Entity
#Table(name = "`order`")
public class Order implements Serializable {
#Id
#GeneratedValue
private Long id;
// Order columns...
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "order_id")
private Set<Item> items;
}
The item:
#Entity
#Table(name = "item")
public class Item implements Serializable {
#Id
#GeneratedValue
private Long id;
// Item columns...
#ManyToOne(optional = false)
#JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false)
private Order order;
}
in adress class
#OneToOne(mappedBy="adress")
private User user;
and in user class
#OneToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER,optional=false)
#PrimaryKeyJoinColumn
private Adress adress;

Hibernate Mapping when foreign key placed in reference class

I have two classes Student and Address.
Student{
stuid,
stuName,
}
Address{
street,
city,
stuid;//foriegn key Ref with Studnet
}
Can any one help me to map these two classes using hibernate??
You should learn what is OneToOne mapping in hibernate firstly.
Secondly if I would want to design then I would have address_id as foreign key in Student table and not student id.
//Table name will be taken as Student as you are not specifying it using #Table annotation
Student class
#Entity
public class Student{
#Id
#Column("stuid")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column("stuName")
private String name;
//setters and getters
}
Address class
#Entity
public class Address{
#Id
#Column("add_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column("street")
private String street;
#Column("city")
private String city;
#OneToOne(cascade={CascadeType.SAVE,CascadeType.MERGE})
#JoinColumn(name="stuid")
private Student student
//setters and getters
}
Suppose if a Student can have multiple Address entities then you need to have one-to-many relationship between Student and Address classes. A student should know what addresses they belong to and also as you need to save the student id in address table then the relationship becomes bi-directional.
The entities looks like this:
Student.java
#Entity
#Table(name = "student_tbl") // Optional, By default table name is student, if you want to give different name then use this line.
public class Student1 {
#Id
#GeneratedValue
private int stuid;
private String stuName;
#OneToMany(mappedBy = "student")
private List<Address> address = new ArrayList<Address>();
// Setters & Getters
}
Address.java
#Entity
#Table(name = "address_tbl")
public class Address {
#Id
#GeneratedValue
private int addressId;
private String street;
private String city;
#ManyToOne
#JoinColumn(name="stuid")
private Student1 student;
// Setters & Getters
}

OneToOne with the same PrimaryKey and ForeignKey

Database
*user_account*
id (PK)
email
password
*user_detail*
id(PK)(FK)
name
city
Entities
#Table(name="user_detail")
public class UserDetail implementsSerializable{
#Id private Integer id;
...
#OneToOne
#JoinColumn(name="id")
private UserAccount userAccount;
}
#Table(name="user_account")
public class UserAccount implementsSerializable{
#Id private Integer id;
#OneToOne(mappedBy="userAccount")
private UserDetail userDetails;
}
Error
Exception Description: Multiple writable mappings exist for the field [user_detail.ID]. Only one may be defined as writable, all others must be specified read-only.
If the ID in UserAccount is both a primary key and a foreign key, then you should declare it as a single field and map it appropriately. Like this:
#Entity
public class UserAccount implements Serializable {
#Id
#OneToOne(mappedBy="userAccount")
private UserDetail userDetails;
}
Or else using #MapsId.
However, i suspect that what you really want is a single class spread over two tables:
#Entity
#Table(name = "user_account")
#SecondaryTable(name = "user_detail")
public class User implements Serializable {
#Id
private int id;
private String email;
private String password;
#Column(table = "user_detail")
private String name;
#Column(table = "user_detail")
private String city;
}
You cannot have both #Id private Integer id; and #JoinColumn(name="id"), you must remove one of them: I doubt that you really need a primary key in the details, so just remove the #Id line from there.

Categories