Jpa #OnetoOne relationship - java

This is my entity class Author
#Entity
#Column(name = "ID")
private Long id;
#Column(name = "LAST1")
private String last;
#Column(name="FIRST1")
private String first;
#Lob
#Column(name = "BIO")
private String bio;
#OneToOne
private AuthorDetail authorId;
getters and setters & zero parameter constructor
this is my other entity AuthorDetail here i have mapped using #OneToOne(optional = false,mappedBy = "authorDetail")
#Column(name = "ID")
private Long id;
#Column(name = "ADDRESS1")
private String address1;
#Column(name="ADDRESS2")
private String address2;
#Column(name = "CITY")
private String city;
#Column(name = "STATE1")
private String state;
#Column(name = "ZIP")
private String zip;
#Column(name = "START_DATE")
#Temporal(TemporalType.DATE)
private Date startDate;
#Lob
#Column(name = "NOTES")
private String notes;
#OneToOne(optional = false,mappedBy = "authorDetail")
private Author authorId;
getters and setters
this my main class
`EntityTransaction entr=em.getTransaction();
entr.begin();
Author author=new Author();
author.setFirst("MD");
author.setLast("RAHMATH");
author.setBio("A Software Developer");
Set detailSet=new HashSet<AuthorDetail>();
AuthorDetail detail=new AuthorDetail();
detail.setAddress1("Address1");
detail.setAddress2("Address2");
detail.setCity("NoMansLand");
detail.setState("ZZ");
detail.setZip("12345");
detail.setNotes("This is test detail");
detailSet.add(detail);
em.persist(author);
entr.commit();`
i am getting exceptions if i try run the program

If you want a single-directional relation, you don't need to write #OneToOne in both class.
From the given piece of code, it appears that you want the bi-direction relationship between Author detail and Author.
For the other side to be aware of the relation (bidirectional), it is required to add the mappedBy attribute to the #OneToOne annotation. This attribute references the (Java) property in the entity that is the owner of the relationship. In your case, in AuthorDetail class you need to add;
#OneToOne(optional = false,mappedBy = "authorId")
private Author authorId;
In mappedBy property, you need to give reference to the entity not class name.

In your Author change the following:
#OneToOne
private AuthorDetail authorId;
To:
#OneToOne
private AuthorDetail authorDetail;

Related

Hibernate Invalid Path Exception

New to Hibernate and HQL in general. I have these following entities.
Employee entity
public class Employee implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column
private Integer authority;
#Column
private String username;
#Column(name = "user_password")
private String password;
#Column
private String title;
#OneToOne
#JoinColumn(name = "person_id", referencedColumnName = "id")
private Person person;
#Column
private Integer gender;
#Column
private String ssn;
#Column(name = "car_info")
private String carInfo;
#Column(name = "birth_date")
private Date birthDate; //java.util Date vs java.sql.Date?
#OneToOne
#JoinColumn(name = "visa_status_id", referencedColumnName = "id")
private VisaStatus visaStatus;
#Column(name = "license_number")
private Integer licenseNumber;
#Column(name = "license_expiration_date")
private Date licenseExpirationDate;
#ManyToOne
#JoinColumn(name = "housing_id", referencedColumnName = "id")
private House house;
}
Person entity
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "middle_name")
private String middleName;
#Column(name = "preferred_name")
private String preferredName;
#ManyToOne
#JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
#Column
private String email;
#Column(name = "ceil_phone")
private String ceilPhone;
#Column(name = "work_phone")
private String workPhone;
}
House entity
public class House implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToOne
#JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
#ManyToOne
#JoinColumn(name = "contact_id")
private Contact contactHR;
#ManyToOne
#JoinColumn(name = "landlord_id")
private Person landlord;
}
I'm trying to run this HQL:
select person from Employee where house.id=:houseId
I'm basically trying to get all the Person with the houseId from the Employee. Since I'm trying to only get the person, I'm using the select cause.
But I'm getting these errors:
org.hibernate.hql.internal.ast.InvalidPathException: Invalid path: 'house.id'
org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'house.id' [select person from example.project.domain.entity.Employee where house.id=:houseId]
I tried the HQL without the select clause and it worked:
from Employee where house.id=:houseId
But I only need person so I didn't want to get everything. Any idea what's wrong?
You asked
Hibernate Invalid Path Exception using HQL
The problem lies on the written query
select person from Employee where house.id=:houseId
Which should contain proper referencing
select p.person from Employee p where p.house.id=:houseId
Why ?
The FROM clause defines which entities the data is going to be selected. Hibernate, or any other JPA implementation, maps the entities to the according database tables and the syntax of a JPQL FROM clause is similar to SQL and indeed uses the entity model for referencing database attributes, which in root query execution (same thing you are doing) one must use the same referencing strategy, which in your case is to use aliases, as A.Panfilov said in comments regardless of hibernate, even in aliasing in SQL is a good practice.
You may find more in here.

Java Hibernate Database speed issue

I generated application using Jhipster. In start everything was working fine but as application grow tournament entity become issue regarding performances.
This is my entity :
/**
* A Tournament.
*/
#Entity
#Table(name = "tournament")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "tournament")
public class Tournament implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "name")
private String name;
#Column(name = "location")
private String location;
#Column(name = "url")
private String url;
#Column(name = "start_date")
private ZonedDateTime startDate;
#Column(name = "end_date")
private ZonedDateTime endDate;
#Column(name = "entry_fee")
private Double entryFee;
#Column(name = "prize")
private Double prize;
#Column(name = "goods")
private String goods;
#Column(name = "favorite_rating")
private Long favoriteRating;
#Column(name = "participants_number")
private Integer participantsNumber;
#Column(name = "finished")
private Boolean finished;
#Column(name = "view_only")
private Boolean viewOnly;
#Column(name = "image")
private String image;
#Column(name = "description")
private String description;
#Column(name = "teams_applied")
private String teamsApplied;
#Lob
#Column(name = "schedule")
private String schedule;
#Lob
#Column(name = "prize_distribution")
private String prizeDistribution;
#Lob
#Column(name = "contacts")
private String contacts;
#Lob
#Column(name = "rules")
private String rules;
#OneToMany(mappedBy = "tournament", fetch = FetchType.LAZY)
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Stream> streams = new HashSet<>();
#ManyToMany
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#JoinTable(name = "tournament_platforms", joinColumns = #JoinColumn(name = "tournaments_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "platforms_id", referencedColumnName = "id"))
private Set<Platform> platforms = new HashSet<>();
#ManyToMany(mappedBy = "favoriteTournaments", fetch = FetchType.LAZY)
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<User> favoriteUsers = new HashSet<>();
#ManyToOne
private Game game;
#ManyToOne
private TournamentStatus status;
#ManyToOne
private EntryType entryType;
#ManyToOne
private TournamentFormat format;
#ManyToOne
private Region region;
#ManyToOne
private GameMode gameMode;
#ManyToOne
private PrizeType prizeType;
#ManyToOne
private Organizer organizer;
#ManyToOne
private TournamentStage stage;
#ManyToOne
private HostPlatform hostPlatforms;
#ManyToOne
private TournamentType type;
#ManyToOne
private PlayType playType;
#ManyToOne
private Currency currency;
#ManyToOne
private Country country;
I am using spring JPA. Getting 20 tournaments from database takes 39 seconds. That is not acceptable. Is there any way i can reduce it to normal speed. What is reason for such a long response time ? Every many to one relation i made unidire
In hibernate's implementation of JPA, #ManyToOne has a fetchType = EAGER by default and you have 14 of them.
#ManyToOne
private Country country;
That means 14 joins for each request. I highly recommend to use fetchType = LAZY for all relationships and deactivate them one by one when needed.
As a rule of thumb, you should not use more than 3 joins per request.
Also take a look at the generated request and use EXPLAIN PLAN in order to understand what the database really does and where it is costly. It will probably reveal some missing indexes on columns used as foreign keys...

JPA many to many relation in Spring Boot app doesn't work

I want to create a many to many relation in my application but it doesen't work.
My first entity:
#Entity
#Table(name = "Person")
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Version
private Long version;
private String firstName;
private String lastName;
private String location;
private String email;
private String status;
private String role;
private LocalDateTime createdOn;
private LocalDateTime modifiedOn;
#ManyToMany(mappedBy = "persons")
private Set<Team> teams = new HashSet<Team>();
My second entity:
#Entity
#Table(name = "Team")
public class Team {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Version
private Long version;
private String name;
private String description;
private String city;
private Integer headcount;
private LocalDateTime createdOn;
private LocalDateTime modifiedOn;
#ManyToMany(cascade = CascadeType.MERGE)
#JoinTable(name = "persons_teams",
joinColumns = #JoinColumn(name = "teamId"),
inverseJoinColumns = #JoinColumn(name = "personId"))
private Set<Person> people = new HashSet<>();
I don't know what is wrong but the program doesn't compile.
Please help.
In Person class you have indicated the name of field to be mapped in Team by using name "persons" but the actual field name in Team class is "people".

Hibernate not setting foreign constrains

I am developing an application using Spring and Hibernate. Below are my model bean classes:
Employee
#Entity
#Table(name="employee")
public class Employee {
#Id
#Column
#GeneratedValue
private int empid;
#Column
private String firstName;
#Column
private String lastName;
#Column
private String email;
#Column
private String password;
#Column
private boolean isAdmin;
#Column
private boolean isActive;
#Column
private boolean isLocked;
//getter and setter
PersonalDetails
public class PersonalDetails {
#Column
#Id
private int empid;
#Column
private String personalEmail;
#Column
private String mob;
#Column
private String permenantAdress;
#Column
private String currentAddress;
#Column
private String gender;
#Column
private String maritialStatus;
#OneToOne
#PrimaryKeyJoinColumn
#ForeignKey(name="empid")
private Employee employee;
//getter and setter
My tables get created automatically on the server startup but foreign key constraint in PersonalDetails table is not getting set.
Did I missed anything here?
I think your #OneToOne mapping should be as follows:
#MapsId
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "empid", referencedColumnName = "empid")
private Employee employee;
The cascade attribute is optional, but a good practice.

#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;

Categories