I have a problem with spring boot inheritance classes - mysql

I have a user class which is a supper class and a student class a subclass of users. I don’t have an error in the code but I don't why it does not make tables in the database when I remove "extends user" it creates the table?
here is my code
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Data
public abstract class User {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
private String password;
#Enumerated(EnumType.STRING)
#Column(length = 20)
private Role name;
}
#Entity
#Table(name = "student")
#Data
public class Student extends User{
#Id
private Long id;
private LocalDate dob;
private String tell;
private String course;
}

In this link you can have an overview of the following approaches to inheritance:
MappedSuperclass - the parent classes, can't be entities
Single Table -The entities from different classes with a common ancestor are placed in a single table.
Joined Table - Each class has its table, and querying a subclass entity requires joining the tables.
Table per Class -All the properties of a class are in its table, so no join is required.
Regards

Related

Mapping EXCEL Sheet to Database using JPA Hibernate

I would like to map an simple excel table to my javaEE application using hibernate. I'm really new to Databases and ORM so i would like to know if the following relations make sense and in how many Entities would make sense to split the Table.
This is the attributes contained in the Excel spreadsheet:
(Office Room Number|ComputerName|ComputerIP|Computer OS|UserFirstName|UserLastName)
Relations:
OfficeRoomNumber -- 1 : N -- Users
N users working in 1 Office?
OfficeRoomNumber -- 1 : N -- Computer
N Computers are in 1 Office ?
User -- 1:1 -- Computer
1 User got 1 Computer?
Thanks for any help and sorry for my horrible English.
Here are my 50c for modelling your domain. First, one can use an abstract base class for generic aspects, such as primary key generation:
#MappedSuperClass
public abstract class AbstractEntity {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pk-sequence")
#SequenceGenerator(name = "pk-sequence", sequenceName = "ID_GEN", allocationSize = 1)
protected Long objectID = -1;
#Version
private int version;
public int getVersion() {
return version;
}
public long getObjectID() {
return objectID;
}
}
Note well, this can be enhanced to include other generic aspects, e.g. creation/modification date/timestamps.
Next, we introduce three domain classes/entities as follows:
#Entity
public class OfficeRoom extends AbstractEntity {
private String name;
private String roomNumer;
#ManyToMany // Maybe an employee is associated with 2 or more office places she/he might work at?
private Collection<Employee> staff;
#OneToMany(mappedBy="location")
private Collection<Computer> equipment;
// getters and setters
}
I added a comment as you can see above on the field staff. Potentially, one would like to associated two different office rooms to certain VIP staff, so you should consider this case in modelling your domain by using #ManyToMany here already.
Moving on with:
#Entity
public class Computer extends AbstractEntity {
private String name;
private String model;
private String vendor;
private String installedOS;
private String ipAddress;
#ManyToOne
private OfficeRoom location;
#OneToMany(mappedBy="machine") // Maybe a computer is associated with 2 or more employees?
private Collection<Employee> user;
// getters and setters
}
Again, consider my comment carefully. Finally,...
#Entity
public class Employee extends AbstractEntity {
private String firstName;
private String lastName;
// other staff related attributes here ...
#ManyToOne
private Computer machine;
// getters and setters
}
Note well: Use only annotations originating from the javax.persistence package, in your import statements to stay compliant with the JPA 2.x specification and remain JPA-provider neutral with your application.
Hope this helps.

Spring Data JPA #OneToMany infinite loop exception

OneToMany relationship causing infinite loop using Spring Data JPA with hibernate as provider
The problem here is not the type of exception but the infinite loop that causes this exception
I tried #JsonIgnoreProperties which gives me another error => 'Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer'
The post referencing the solution does not have a solution that adresses my problem.
One says use #JsonManagedReference and #JsonBackReference that does stop the recursion but excludes the object (UserGroup in 'myUser' entity) from the result which I need when I want an object of 'myUser' entity.
The other one says about overriding ToString method which I don't do.
Another one explains why there is an infinite loop and suggest as solution to not do that way. I quote "Try to create DTO or Value Object (simple POJO) without cycles from returned model and then return it."
And this one Difference between #JsonIgnore and #JsonBackReference, #JsonManagedReference explains the difference but doing so I will have the same problem as the first one
'myUser' entity
#Entity
public class MyUser {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private String email;
private Integer age;
//#JsonIgnoreProperties({"myUsers"})
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "userGroupId")
private UserGroup userGroup;
'UserGroup' entity
#Entity
public class UserGroup {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer groupOrder;
#OneToMany
(
mappedBy = "userGroup",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<MyUser> myUsers;
change the getUserGroup() method in your MyUser class as follows.
#Entity
public class MyUser
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private String email;
private Integer age;
//#JsonIgnoreProperties({"myUsers"})
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "userGroupId")
private UserGroup userGroup;
public UserGroup getUserGroup()
{
userGroup.setMyUsers(null);
return userGroup;
}
}
you need to add #JsonIgnore annotation at #OneToMany
like this
#JsonIgnore
#OneToMany
(
mappedBy = "userGroup",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<MyUser> myUsers;
I think I'm getting the point of your problem. You want to fetch MyUser including the userGroup data without the circular reference.
Based from the solutions you enumerated, I suggest you should still use the #JsonBackReference and #JsonManagedReference to prevent recursion on your entities and for the solution on your problem, you can try to use a mapper (MapStruck) and map the userGroup details to a DTO during the retrieval of data from the service.
DTOs:
public class MyUserDto {
private Long id;
private String firstName;
private String lastName;
private String email;
private Integer age;
private UserGroupDto userGroupDto;
}
public class UserGroupDto {
private Long id;
private Integer groupOrder;
}
Mapper (MapStruck):
#Mapper(componentModel = "spring")
public interface MyUserMapper {
MyUserMapper INSTANCE = Mappers.getMapper(MyUserMapper.class);
UserGroupDto userGroupToDto(UserGroup userGroup);
#Mapping(source = "myUser.userGroup", target = "userGroupDto")
MyUserDto myUserToDto(MyUser myUser);
}
After retrieving the data from your repository, you may then call the myUserToDto method to map the entity to a DTO.
This is just one way of solving your problem.

Setting relationship in Model class does not create db table entries in playFramework

I create 3 model classes in playframework, and set one-one relationship and one-to many relationship in one of the class. The code snippet are as follows:
Person.java
///////////////////////
#Entity
#Table(name = "person")
public class Person extends Model{
#Id
private Long id;
private String lastName;
private String firstName;
private String userId;
private Address address;
private List<Task> tasks;
....
}
Task.java
//////////////////////////
#Entity
#Table(name = "task")
public class Task extends Model{
#Id
private Long id;
private String name;
private String descript;
private String details;
...........
}
Address.java
////////////////////
#Entity
#Table(name = "address")
public class Address extends Model{
#Id
private Long id;
private String street;
private String state;
.........
}
I create person object and set the attributes/one-one/one-many relationships.
I try to save the person object with both attributes and relationships to mysql db by calling person.save().However, it ends up saving only attributes userId/firstName/LastName. the address object and tasks list object are not saved in db.
My question is : is there any way to save the relationship objects in db long with person.save()? that is , after calling person.save(), address table and task table create new entires corresponding to them.
I end up setting foreign keys in person class to handle this relationship manually.
Thanks in advance!
You might want to have a look at a JPA tutorial in particular topics about #OneToMany and #OneToOne annotations. I'd recommend https://en.wikibooks.org/wiki/Java_Persistence/OneToMany and https://en.wikibooks.org/wiki/Java_Persistence/OneToOne.

How to JSON a hibernate tree node

#Entity
public class Group{
#Id
#GeneratedValue
private Long id;
#ManyToOne
private Group parent;
#LazyCollection(value=LazyCollectionOption.FALSE)
#OneToMany(mappedBy = "parent")
#Cascade(value = {CascadeType.ALL})
private Set<Group> children = new HashSet<Group>();
}
How do I JSON that structure? Json goes to infinite recursion .. Im using Jackson.
I need to have parent ID in my json output also .
set a #JsonBackReference on the #ManyToOne property and a #JsonManagedReference on the #OneToMany property
#Entity
public class Group{
#Id
#GeneratedValue
private Long id;
#JsonBackReference
#ManyToOne
private Group parent;
#JsonManagedReference
#LazyCollection(value=LazyCollectionOption.FALSE)
#OneToMany(mappedBy = "parent")
#Cascade(value = {CascadeType.ALL})
private Set<Group> children = new HashSet<Group>();
}
If the Competency entity points to a Group, then you might indeed go into infinite recursion. You can put a #JsonIgnore annotation on the parent and children instance variables to ignore them from being included in the JSON, or you can use a combination of #JsonBackReference/#JsonManagedReference, as the other poster suggested.
Other thing you can do is create a pojo which contains all the properties you are interested in in your service layer, cutting the hibernate connections out of the picture. Something like that:
public class GroupDto {
private Long id;
private CompetencyDto parent;
private List<CompetencyDto> children;
}
public class CompetencyDto {
private Long id;
}
This, while seeming like overwork, would give you the power your presentation model to not be dependent on your domain model. This would give you much more flexibility when constructing your views:
http://codebetter.com/jpboodhoo/2007/09/27/screen-bound-dto-s/
http://martinfowler.com/eaaDev/PresentationModel.html

How to fetch data from One To One Relationship in SubQuery using Hibernate in spring

I have two table hesk_users, user as under.
#Entity
#Table(name="hesk_users")
public class UserHesk {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column
private int id;
#OneToOne
#JoinColumn(name="user_id")
private User user;
set.... get..
}
#Entity
#Table(name="user")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#NotEmpty
#Column
private String firstname;
#OneToOne(mappedBy="user")
private UserHesk userHesk;
set ... get ...
}
I have hibernate query but it not working..
DetachedCriteria detachedCriteria=DetachedCriteria.forClass(UserHesk.class)
.setProjection(Projections.property("user_id"));
Criteria criteria=sessionFactory.getCurrentSession().createCriteria(User.class);
criteria.add(Property.forName("id").notIn(detachedCriteria));
User user=(User)criteria.list().get(0);
System.out.println(user.getFirstname());
System.out.println("Subquery Size "+criteria.list().size());
Error for user_id filed. which can not be get because of relationship.
HQL and criteria queries always use the entity classes and properties. Never the names of the underlying tables and columns. The UserHesk class doesn't have any user_id property. It has a user property.
So the code should be
DetachedCriteria detachedCriteria =
DetachedCriteria.forClass(UserHesk.class)
.setProjection(Projections.property("user.id"));
or even
DetachedCriteria detachedCriteria =
DetachedCriteria.forClass(UserHesk.class)
.createAlias("user", "u")
.setProjection(Projections.property("u.id"));