SpringData cascade update - java

This is the first entity:
#Entity
#Table(name = "photographers")
public class Photographer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotNull
#Column(name = "first_name")
private String firstName;
#NotNull
#Size(min = 2, max = 50)
#Column(name = "last_name")
private String lastName;
#Pattern(regexp = "^\\+[0-9]{1,3}/[0-9]{8,10}$")
private String phone;
#NotNull
#OneToOne(optional = false)
#JoinColumn(name = "primary_camera_id", referencedColumnName = "id")
private BasicCamera primaryCamera;
#NotNull
#OneToOne(optional = false)
#JoinColumn(name = "secondary_camera_id", referencedColumnName = "id")
private BasicCamera secondaryCamera;
#OneToMany(mappedBy = "owner")
private Set<Lens> lenses;
#OneToMany(mappedBy = "owner")
private Set<Accessory> accessories;
and this is the other(lenses) :
#Entity
#Table(name = "lenses")
public class Lens {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String make;
#Column(name = "focal_length")
private Integer focalLength;
#Column(name = "max_aperture", precision = 1)
private Double maxAperture;
#Column(name = "compatible_with")
private String compatibleWith;
#ManyToOne
#JoinColumn(name = "owner_id", referencedColumnName = "id")
private Photographer owner;
Firstly i have lenses without owners. Then i want to create a photographer with everything and set its lenses to exiting ones i do this with this code:
for (Lens lens : lensSet) {
lens.setOwner(photographer);
}
photographer.setPrimaryCamera(primaryCamera);
photographer.setSecondaryCamera(secondaryCamera);
photographer.setLenses(lensSet);
and when i save the photographer i want the lenses owner to be set to the created one. I tried cascad.MERGE on the OneToMany realation in the photographer entity but did't work and in the database all lenses owners are still nulls

I figured it out : i need to save the lenses AFTER i save the photographer:
for (Lens lens : lensSet) {
lens.setOwner(photographer);
}
photographer.setPrimaryCamera(primaryCamera);
photographer.setSecondaryCamera(secondaryCamera);
photographer.setLenses(lensSet);
this.photographerRepository.save(photographer);
this.lensRepository.save(lensSet);

Related

Jpa repository filter by enum value

public class EmployeeEntity {
#Id
#Column(name = "id")
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#Length(min = 2, max = 30)
#Column(name = "name")
private String name;
#Length(min = 2, max = 30)
#Column(name = "last_name")
private String lastName;
#Column(name = "email", nullable = false, unique = true)
#Length(max = 50)
private String email;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "employee_id")
private Set<EmployeeRoleEntity> roles;}
This is my Employee class and as you can see inside Employee, I have a set of EmployeeRoleEntity
public class EmployeeRoleEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#NotNull
#Column(name = "role_name")
#Enumerated(EnumType.STRING)
private RoleEntityEnum role;
#ManyToOne
#JoinColumn(name = "employee_id")
#ToString.Exclude
#EqualsAndHashCode.Exclude
private EmployeeEntity employee;
I was trying to filter my employees depends in their role. I created a method like this on my Jpa repository;
List<EmployeeEntity> findByRoles_RoleContainingIgnoreCase( String role);
But it doesn't work and Im so confused to what to do. How can I solve this problem?
Finally I found the answer;
List<EmployeeEntity> findByRoles_Role( RoleEntityEnum role);
This solved my problem. I thought at first the problem was the method but appearently the problem was parameter.

Spring data JPA one to Many / Many to one not inserting/updating details in database

Am doing one small activity of Teach and address relationship for one to many and in address block there will be one to one relationship between country, district, tahasil etc. Whenever am hitting api and to save it it's not updating or inserting Address in address table.
Detail is
#Entity
#Table(name = "teachers")
#PrimaryKeyJoinColumn(name = "user_id")
public class Teacher extends User {
#Size(min = 3, max = 50)
#Column(name = "first_name")
private String firstName;
#Size(min = 3, max = 50)
#Column(name = "middle_name")
private String middleName;
#Size(min = 3, max = 50)
#Column(name = "last_name")
private String lastName;
#OneToMany(fetch = FetchType.LAZY,mappedBy = "teacher")
#JsonManagedReference
private Set<Address> addresses = new HashSet<>(0);
Getter Setter...
}
Then Address Entity
#Entity
#Table(name = "address")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "address_id")
private Long addressId;
#ManyToOne (fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
#JsonBackReference
private Teacher teacher;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "country_id", referencedColumnName = "country_id")
private Country country;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "state_id", referencedColumnName = "state_id")
private State state;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "district_id", referencedColumnName = "district_id")
private District district;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "tahasil_id", referencedColumnName = "tahasil_id")
private Tahasil tahasil;
#Column(name = "line_one")
private String lineOne;
#Column(name = "line_two")
private String lineTwo;
#Column(name = "landmark")
private String landmark;
#Column(name = "pincode")
private Integer pincode;
public Country getCountry() {
return country;
}
Other Getter Setter
The Country example same to state, district and tahasil
#Entity
#Table(name = "countries", uniqueConstraints = { #UniqueConstraint(columnNames = { "country_name" }) })
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "country_id")
private Long countryId;
#NotBlank
#Size(min = 3, max = 50)
#Column(name = "country_name")
private String countryName;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "country")
private Address address;
Getter Setter
Finally in controller am doing like
Optional<Teacher> teacher = teacherRepo.findByUserId(id);
if (!teacher.isPresent())
return ResponseEntity.notFound().build();
teacher.get().setUserId(id);
teacher.get().setFirstName(teacherUpdateForm.getFirstName());
teacher.get().setMiddleName(teacherUpdateForm.getMiddleName());
teacher.get().setLastName(teacherUpdateForm.getLastName());
teacher.get().setAddresses(teacherUpdateForm.getAddresses());
userRepository.save(teacher.get());
Tried so may ways by referring multiple sites and readouts, but still not able to see any insert or update to address table. Please help me to get my mistake.
Regards,
Chetan
You need to cascade the persist of the Teacher entity.
Update the definition of the attribute Address inside the Teacher entity:
#OneToMany(fetch = FetchType.LAZY,mappedBy = "teacher", cascade = CascadeType.ALL)
#JsonManagedReference
private Set<Address> addresses = new HashSet();
You can play with the cascade type value as you want.

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...

Spring Cannot add foreign key constraint #ManyToOne

I've tried to make this Entity:
#Entity
#Table(name = "rate")
public class Rate {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "rate_id")
private Long id;
#ManyToOne
#JoinColumn(name = "user_id")
private User answerer;
#ManyToOne
#JoinColumn(name = "answer_id")
private Answer answer;
#Column(name = "rate_rate")
private Integer rate = AnswerConstants.MAX_RATE;
//pluss getter-setters
}
Unfortunately, I get this error:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Unable to execute schema management to JDBC target [alter table rate add constraint FK8totaejp8tp48clsoikn05fn2 foreign key (answer_id) references answer (answer_id)]
I've Googled for about an hour but I could not found the solution. Can you help me? Why am I getting this?
Additionally: spring.jpa.hibernate.ddl-auto=update, if I turn it off, it solves the problem but I do not want to do that just because of this.
The Answer class looks like this:
#Entity
#Table(name = "answer")
public class Answer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "answer_id")
private Long id;
#Column(name = "answer_text")
#NotEmpty
private String answerText;
#ManyToOne
#JoinColumn(name = "user_id")
private User answerCreator;
#ManyToOne
#JoinColumn(name = "question_id")
private Question question;
#Column(name = "answer_creation_date")
#NotNull
private Date creationDate = new Date();
#Column(name = "answer_rate")
private Long answerRate = 1l;
//plus getters-setters
}
And the User class:
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private Long id;
#Column(name = "email")
#Email(message = "*Please provide a valid Email")
#NotEmpty(message = "*Please provide an email")
private String email;
#Column(name = "password")
#Length(min = 5, message = "*Your password must have at least 5 characters")
#NotEmpty(message = "*Please provide your password")
#Transient
private String password;
#Column(name = "active")
private int active;
#ManyToMany()
#JoinTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
//Plus getters-setters
}
Try passing name with referencedColumnName with #JoinColumn annotation. It worked for me.
#ManyToOne(optional = false)
#JoinColumn(name = "userTypeId", referencedColumnName = "id",nullable = false)
private UserType userType;
My entities were User and UserType where User have an attribute "userTypeId" as the foreign key.

Hibernate annotation mapping, complicated diagram

I have some big problems with making a proper mapping for delivered diagram. It looks like this:
Now, so far I did this, hopefully its ok (ommited getters/setters). You'll notice that USERS has DOMAIN_ID, ignore it as it is not full diagram.
FunctionalityGroup
#Entity
#Table(name = "FUNCTIONALITY_GROUP")
public class FunctionalityGroup implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "FUNCTIONALITY_GROUP_ID")
private Long functionalityGroupId;
#Column(name = "FUNCTIONALITY_GROUP_NM")
private String functionalityGroupName;
#Column(name = "FUNCTIONALITY_GROUP_DESC")
private String functionalityGroupDesc;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "funcionalityGroupId")
private List<Functionality> functionalityList;
}
Functionality
#Entity
#Table(name = "FUNCTIONALITY")
public class Functionality implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "FUNCTIONALITY_ID")
private Long functionalityId;
#Column(name = "FUNCTIONALITY_NM")
private String functionalityGroupName;
#Column(name = "FUNCTIONALITY_DESC")
private String functionalityGroupDesc;
#Column(name = "FUNCTIONALITY_GROUP_ID")
private Long funcionalityGroupId;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "ROLE_FUNCTIONALITY",
joinColumns = {#JoinColumn(name = "FUNCTIONALITY_ID")},
inverseJoinColumns = {#JoinColumn(name = "ROLE_ID")})
private List<Role> roleList;
}
Role
#Entity
#Table(name = "ROLE")
public class Role implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ROLE_ID")
private Integer roleId;
#Column(name = "ROLE_NM")
private String roleName;
#Column(name = "ROLE_DESC")
private String roleDesc;
#Column(name = "OBJECT_TYPE")
private String objectType;
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "roleList")
private List<Functionality> functionalityListy;
}
Users
#Entity
#Table(name = "USERS")
public class Users implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "USER_ID")
private Long userId;
#Column(name = "USER_DESC")
private String userDesc;
#Column(name = "FIRST_NM")
private String firstNM;
#Column(name = "LAST_NM")
private String lastNM;
#Column(name = "IS_ENABLED")
private String isEnabled;
}
I have no idea how Role_Member and Role_Member_Entry should be mapped and handled withing object world, could somebody give me some hits? Thanks!
Normally I'd connect Users with Role as Many to Many, but the entity Role_Member_Entry ruins everything.

Categories