i want to store the JSON using spring boot with JPA - spring

{ "id" :"3",
"userId": "abc",
"favName": "shashank",
"kpiName": "FavKPI",
"rptId": "529",
"language": "EN",
"selectedControlIdList": [
{
"favouriteId": 3,
"controlId": "3",
"controlName": " ",
"label": "Plant",
"keyValue": "KPI_01_PL_01_1",
"structureType": "LISTBOX"
},
{
"favouriteId": 3,
"controlId": "2",
"controlName": " ",
"label": "Plant12",
"keyValue": "KPI_01",
"structureType": "LISTBOX"
}
]
}
My controller class is
#RequestMapping(value = "/addFavData", method = RequestMethod.POST, consumes =MediaType.APPLICATION_JSON_VALUE, produces =MediaType.APPLICATION_JSON_VALUE)
public void addFavData(#RequestBody FavouriteDTO requestInputMapper) {
favouriteService.addFavouriteData(requestInputMapper);
}
service class
public void addFavouriteData(FavouriteDTO requestInputMapper)
{
favouriteRepository.save(requestInputMapper);
}
And these are entity class !!
#Entity
#Table(name = "favorite", schema = "quality")
public class FavouriteDTO implements Serializable{
private static final long serialVersionUID = -7089417397407966229L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "userId")
private String userId;
#Column(name = "favName")
private String favName;
#Column(name = "kpiName")
private String kpiName;
#Column(name = "rptId")
private String rptId;
#Column(name = "language")
private String language;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "favouriteId")
private List<DefaultControlsDTO> selectedControlIdList;
}
And
#Entity
#Table(name = "favoriteControls", schema = "quality")
public class DefaultControlsDTO implements Serializable {
private static final long serialVersionUID = 8720721227933753311L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "favouriteId")
private Integer favouriteId;
#Column(name = "controlId")
private String controlId;
#Column(name = "controlName")
private String controlName;
#Column(name = "label")
private String label;
#Column(name = "keyValue")
private String keyValue;
#Column(name = "structureType")
private String structureType;
}
here the id is auto genrated. and the favouriteId is same as id.
so how can i store the data as id is auto genrated and i need to put the same favourite id as in id. so how can i store the data in the data base
so i have given my entity class. i have two entity Favorite and DefaultFavuorite Entity.so how can i store the data

You can tell Hibernate, and any other JPA implementation, to cascade certain operations you perform on an entity to its associated child entities. The only thing you have to do is to define the kind of operation you want to cascade to the child entities.
The following code snippet shows an example in which I cascade the persist operation of the Author entity to all associated Book entities.
#Entity
public class Author {
…
#ManyToMany(mappedBy=”authors”, cascade = CascadeType.PERSIST)
private List<Book> books = new ArrayList<Book>();
…
}
When you now create a new Author and several associated Book entities, you just have to persist the Author entity.
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Author a = new Author();
a.setFirstName(“John”);
a.setLastName(“Doe”);
Book b1 = new Book();
b1.setTitle(“John’s first book”);
a.getBooks().add(b1);
Book b2 = new Book();
b2.setTitle(“John’s second book”);
a.getBooks().add(b2);
em.persist(a);
em.getTransaction().commit();
em.close();
As you can see in the log output, Hibernate cascades the operation to the associated Book entities and persists them as well.
15:44:28,140 DEBUG [org.hibernate.SQL] – insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)
15:44:28,147 DEBUG [org.hibernate.SQL] – insert into Book (publisherid, publishingDate, title, version, id) values (?, ?, ?, ?, ?)
15:44:28,150 DEBUG [org.hibernate.SQL] – insert into Book (publisherid, publishingDate, title, version, id) values (?, ?, ?, ?, ?)

Related

update or delete on table "sessions" violates foreign key constraint "session_schedule_session_id_fkey"

I have to entities modeled Session and Speaker, with ManyToMany relationship, and I wanted to delete an instance of Session, but in the DB it is the foreign key of another table. Below is the entity model
#Entity(name = "sessions")
public class Session {
// attributes do not respect camel case notations because they
// need to match table notations in order to auto bind without annotations
// otherwise that is done with #Column annotation
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long session_id;
private String session_name;
private String session_description;
private String session_length;
#OnDelete(action = OnDeleteAction.CASCADE)
#ManyToMany()
#JoinTable(
name = "session_speakers",
joinColumns = #JoinColumn(name = "session_id"),
inverseJoinColumns = #JoinColumn(name = "speaker_id")
)
private List<Speaker> speakers;
public Session() {
}
I tried to use OnDelete Cascade, but it still didn't work. (I did read that it is not advised to use on ManyToMany relationship)
#RequestMapping(value = "{id}", method = RequestMethod.DELETE)
public void delete(#PathVariable Long id){
sessionRepo.deleteById(id);
}
EDIT:
here is also the Speaker entity
#Entity(name = "speakers")
public class Speaker {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long speaker_id;
private String first_name;
private String last_name;
private String title;
private String company;
private String speaker_bio;
#Lob
#Type(type = "org.hibernate.type.BinaryType")
private Byte[] speaker_photo;
public Byte[] getSpeaker_photo() {
return speaker_photo;
}
public void setSpeaker_photo(Byte[] speaker_photo) {
this.speaker_photo = speaker_photo;
}
#ManyToMany(mappedBy = "speakers")
#JsonIgnore// added to resolve serialization issues
private List<Session> sessions;

how to add object with fk to table in jparepository

i had scheme of user parking and detail parking.
user can park many times (one to many)
im trying to add detail parking object to my db, but i dont have idea how to add the fk from the user in the row of the table, its gave me null there.
(ignore from the logic of the model, i just want to understood the logic how can i the object with fk of ther entity)
this is my code:
#PostMapping("/parking")
public String saveCarParking(#ModelAttribute("user") parkingUsers parkingUsers) {
// parkingUsers[id, firstName, lastName, license]
parkingUsers p = new parkingUsers("jhon", "nash", "248651355");
parkingUsersService.saveParkingUser(p);
// parkingDetails[id, entryDate, entryTime, exitDate, exitTime, user_id(FK)]
parkingDetails d = new parkingDetails(LocalDate.now(), null, LocalDate.now(), null);
parkingDetailsService.saveParkingUser(d);
//how i connect parkingDetails object with fk of parkingUsers?
//it adding now row of parkingDetails but without the fk of user
return "redirect:/parkingList";
}
parking user entity:
#Entity
#Table(name ="users")
public class parkingUsers {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "license")
private String license;
#OneToMany(mappedBy = "parkingUsers", cascade = CascadeType.ALL, orphanRemoval = true)
private List<parkingDetails> parkingDetails = new ArrayList<parkingDetails>();
public parkingUsers() {
}
public parkingUsers(String firstName, String lastName, String license) {
this.firstName = firstName;
this.lastName = lastName;
this.license = license;
}
//setter gettrs and tostring...
entity class of details parking
#Entity
#Table(name ="details")
public class parkingDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "entry_date")
private LocalDate entryDate;
#Column(name = "entry_time")
private LocalDateTime entryTime;
#Column(name = "exit_date")
private LocalDate exitDate;
#Column(name = "exit_time")
private LocalDateTime exitTime;
#ManyToOne
#JoinColumn(name="user_id")
private parkingUsers parkingUsers;
public parkingDetails() {}
public parkingDetails(LocalDate entryDate, LocalDateTime entryTime, LocalDate exitDate, LocalDateTime exitTime) {
this.entryDate = entryDate;
this.entryTime = entryTime;
this.exitDate = exitDate;
this.exitTime = exitTime;
}
//test
// public parkingDetails(LocalDate entryDate, LocalDateTime entryTime, LocalDate exitDate, LocalDateTime exitTime, int user_id ) {
// this.entryDate = entryDate;
// this.entryTime = entryTime;
// this.exitDate = exitDate;
// this.exitTime = exitTime;
// this.parkingUsers.setId(user_id);
// }
//setter gettrs and tostring...
In the ParkingDetails entity, you can have a setter for "parkingUsers" variable to set user object.
In your REST api's saveCarParking() method, before calling "parkingDetailsService.saveParkingUser(d);" you can pass the user object to ParkingDetails using setter created in ParkingDetails.
This should work. No need to explicitly extract the user_id from user's object to pass into ParkingDetails.
Adding one more parameter of type ‘parkingUsers‘ in the constructor of ‘ ParkingDetails’ to initialize user in parking class will also work.
(Apart, it is a good practice to start the class name with a capital letter e.g. instead of having class name as parkingDetails, it should be ParkingDetails.)

How can I retrieve all the children of a record in this Hibernate #ManyToOne relation?

I am working on a Spring Boot project using Spring Data JPA and Hibernate mapping. I have the following doubt about how can I implement the following query.
I have an User entity class like this:
#Entity
#Table(name = "portal_user")
#Getter
#Setter
public class User implements Serializable {
private static final long serialVersionUID = 5062673109048808267L;
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name = "first_name")
#NotNull(message = "{NotNull.User.firstName.Validation}")
private String firstName;
#Column(name = "middle_name")
private String middleName;
#Column(name = "surname")
#NotNull(message = "{NotNull.User.surname.Validation}")
private String surname;
#Column(name = "sex")
#NotNull(message = "{NotNull.User.sex.Validation}")
private char sex;
#Column(name = "birthdate")
#NotNull(message = "{NotNull.User.birthdate.Validation}")
private Date birthdate;
#Column(name = "tax_code")
#NotNull(message = "{NotNull.User.taxCode.Validation}")
private String taxCode;
#Column(name = "e_mail")
#NotNull(message = "{NotNull.User.email.Validation}")
private String email;
#Column(name = "pswd")
#NotNull(message = "{NotNull.User.pswd.Validation}")
private String pswd;
#Column(name = "contact_number")
#NotNull(message = "{NotNull.User.contactNumber.Validation}")
private String contactNumber;
#Temporal(TemporalType.DATE)
#Column(name = "created_at")
private Date createdAt;
#Column(name = "is_active")
private boolean is_active;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
#JsonManagedReference
private Set<Address> addressesList = new HashSet<>();
#ManyToMany(cascade = { CascadeType.MERGE })
#JoinTable(
name = "portal_user_user_type",
joinColumns = { #JoinColumn(name = "portal_user_id_fk") },
inverseJoinColumns = { #JoinColumn(name = "user_type_id_fk") }
)
Set<UserType> userTypes;
#ManyToOne(fetch = FetchType.EAGER)
#JsonProperty("subagent")
private User parent;
public User() {
super();
}
public User(String firstName, String middleName, String surname, char sex, Date birthdate, String taxCode,
String email, String pswd, String contactNumber, Date createdAt, boolean is_active) {
super();
this.firstName = firstName;
this.middleName = middleName;
this.surname = surname;
this.sex = sex;
this.birthdate = birthdate;
this.taxCode = taxCode;
this.email = email;
this.pswd = pswd;
this.contactNumber = contactNumber;
this.createdAt = createdAt;
this.is_active = is_active;
}
}
The instances of this class represents users of my system. An user can have a single specific parent (the concept is similar to that of a referral: an user can bring another user in the system). This is handled by this ManyToOne recursive relationship:
#ManyToOne(fetch = FetchType.EAGER)
#JsonProperty("subagent")
private User parent;
Basically an user contains is parent (who bring him\her into the platform). It works fine. So retrieving an user I can easily retrieve the information of who is its parent (it is contained into the retrieved User object).
Now I need to implement the inverse behavior: I have to define a "query" that starting from a parent retrieve all its children.
The previous User entity class maps the following DB table:
The highlighter parent_id contains the FK that define this recursive relationship. So it contains the PK of another user that is the parent.
I have this UserRepository repository interface (it extents the JpaRepository interface)
public interface UsersRepository extends JpaRepository<User, Integer> {
User findByemail(String email);
List<User> findByUserTypes_TypeName(String typeName);
}
As you can see I am using a "query by method" style. Is it possiblem implement a behavior like this using "query by method" style? (in case also JPQL could be fine)
You can do this
List<User> findByParent_Id(Integer id);
Or you can do this
#Query("SELECT u FROM User u WHERE u.id = ?1")
List<User> getReferredUsers(Integer id);
The relationship between the user and the parent is unidirectional in the given code. By making it bidirectional, it is easy to query the data in either ways.
Refer to below code to make it bidirectional. Also ensure the relevant FetchType to avoid the performance risk. Here FetchType.LAZY is used for one to many association so it queries the data using the proxy reference when needed.
#ManyToOne(fetch = FetchType.EAGER)
#JsonProperty("subagent")
#JsonBackReference
private User parent;
#JsonManagedReference
#OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
private Set<User> userSet = new HashSet<>();
Child entities are fetched only when parent.getUserSet is used because of the FetchType.Lazy
public Set<User> getUsers(int id) {
User parent = userRepository.getById(id);
return parent.getUserSet();
}

ManyToOne FetchType.LAZY does not work. null always returned when getting the list

I am using JPA with Spring Boot. I have entities:
#Entity
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(nullable = false, unique = true)
private String title;
#Column(nullable = false)
private String author;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "bookshelf_id", referencedColumnName = "id", nullable = true)
private Bookshelf bookshelf;
// getter & setter
}
#Entity
public class Bookshelf {
#Id
#GeneratedValue
private long id;
#Column(nullable = false)
private String location;
#OneToMany(mappedBy = "bookshelf", fetch = FetchType.LAZY)
private List<Book> books;
// getter & setter
}
Then in my test, I try to retrieve the book placed in the bookshelf:
Bookshelf shelf = new Bookshelf("room A");
Book book = new Book("a book", "chris");
book.setBookshelf(shelf);;
entityManager.persist(book);
entityManager.persist(shelf);
entityManager.flush();
Bookshelf persistedShelf = bookshelfRepository.findById(shelf.getId()).get();
Book persistedBook = bookRepository.findById(book.getId()).get();
book = null;
shelf = null;
shelf = persistedBook.getBookshelf();
int count = persistedShelf.getBooks().size();
assertEquals(1, count);
The test fails because getBooks() always return null in this line:
int count = persistedShelf.getBooks().size();
Test log shows only two SQL commands are executed:
Hibernate: insert into bookshelf (location, id) values (?, ?)
Hibernate: insert into book (author, bookshelf_id, title, id) values (?, ?, ?, ?)
What can be the problem?
Try also setting the inverse relationship from shelf to book:
Bookshelf shelf = new Bookshelf("room A");
Book book = new Book("a book", "chris");
book.setBookshelf(shelf);
// new code here:
List<Book> books = new ArrayList<>();
books.add(book);
shelf.setBooks(books);
entityManager.persist(book);
entityManager.persist(shelf);
entityManager.flush();
In general you are responsible for managing both sides of the relationship in JPA/Hibernate.

Erroneous POST and PATCH handling of associations with Spring Data Rest

Spring Data Rest is showing a real puzzling behavior when updating an embedded association. In my example there is an entity Customer which has a _OneTo_Many_ relation to an entity Phones. The Phones are correctly shown as embedded array by a GET to the customers/50 entity-resource. But neither the PUT nor the PATCH show the expected results.
public class Customer {
public static final String TABLE_NAME = "CUSTOMER";
public static final String SEQUENCE_NAME = "S_CUSTOMER";
public static final String DISPLAY_NAME_COLUMN = "DISPLAY_NAME";
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "s_customer")
#SequenceGenerator(name = "s_customer", sequenceName = "S_CUSTOMER",
allocationSize = 50)
private Long id;
#NotEmpty
#Column(name = "DISPLAY_NAME")
private String displayName;
#OneToMany(mappedBy = "owner")
private List<Phone> phones;
#Version
private Long version;
}
public class Phone {
public static final String TABLE_NAME = "PHONE";
public static final String SEQUENCE_NAME = "S_PHONE";
public static final String OWNER_COLUMN = "OWNER";
public static final String PHONE_TYPE_COLUMN = "PHONE_TYPE";
public static final String NUMBER_COLUMN = "NUMBER";
enum PhoneType {
MOBILE, HOME, OFFICE
}
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "s_phone_number")
#SequenceGenerator(name = "s_phone_number", sequenceName = SEQUENCE_NAME, allocationSize = 50)
private Long id;
#ManyToOne
#JoinColumn(name = OWNER_COLUMN)
private Customer owner;
#Enumerated(EnumType.STRING)
#Column(name = PHONE_TYPE_COLUMN)
private PhoneType phoneType;
#NotEmpty
#Column(name = NUMBER_COLUMN)
private String number;
#Version
private Long version;
}
A POST to the entity /customer/50 produces a correct Update to the Customer, but the Insert to the Phone does not contain the foreign key to the customer:
[EL Fine]: sql: 2016-06-23
11:41:25.149--ClientSession(1317378011)--Connection(497905718)--Thread(Thread[http-nio-8081-exec-1,5,main])--UPDATE
CUSTOMER SET DISPLAY_NAME = ?, VERSION = ? WHERE ((ID = ?) AND
(VERSION = ?)) bind => [bla, 1, 50, 0] [EL Fine]: sql: 2016-06-23
11:41:25.15--ClientSession(1317378011)--Connection(497905718)--Thread(Thread[http-nio-8081-exec-1,5,main])--INSERT
INTO PHONE (ID, NUMBER, PHONE_TYPE, VERSION, OWNER) VALUES (?, ?, ?,
?, ?) bind => [1, 12345, MOBILE, 1, null]
This is the body of the PUT request:
{
"displayName": "bla",
"phones": [
{
"number": "12345",
"phoneType": "MOBILE"
}
]
}
So, Spring Data Rest correctly interprets the PUT as an update of the Customer and an insert into the Phone table, but just "forgets" about the relation. I assume this is a bug. Or is there something I forgot?
Btw: The PATCH behaves similar. There is again not foreign key in the phone record.
Edit:
The code of the CustomerRepository:
#Repository
public interface CustomerDao extends PagingAndSortingRepository<Customer, Long> {
List<Customer> findByDisplayName(#Param("name") String name);
}

Resources