Find parent element by searching child / Spring boot JPA + PostgresSQL - java

I am trying to figure out how to find and return all Books that are associated with a specific author name.
{
"bookId": 5,
"bookName": "test2",
"publishYear": 2022,
"publisher": "test2",
"authors": [
{
"id": 5,
"name": "Heny",
"surname": "Blakc"
},
{
"id": 6,
"name": "Garyy",
"surname": "Harrys"
}
]
}
I want to return all books where Garyy is the author.
I am using Spring Boot + Postgres SQL OneToMany annotation.
Would appreciate any suggestions.
AuthorController:
package com.example.demo.controller;
import com.example.demo.entity.AuthorEntity;
import com.example.demo.repository.AuthorRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#RestController
#RequestMapping("/author")
public class AuthorController {
#Autowired
AuthorRepository authorRepository;
#GetMapping("/all")
public List<AuthorEntity> author(){
return authorRepository.findAll();
}
#PostMapping("/create")
public AuthorEntity createAuthor(#RequestBody AuthorEntity author){
AuthorEntity savedAuthor = authorRepository.save(author);
return savedAuthor;
}
#GetMapping("/find/{author}")
public List<AuthorEntity> findAuthor(#PathVariable(value = "author") String name){
return authorRepository.findByName(name);
}
}
BookController:
package com.example.demo.controller;
import com.example.demo.entity.BookEntity;
import com.example.demo.repository.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#RestController
#RequestMapping("/book")
public class BookController {
#Autowired
private BookRepository bookRepository;
#GetMapping("/all")
public List<BookEntity> getAllBooks(){
List<BookEntity> allBookList = bookRepository.findAll();
return allBookList;
}
#GetMapping("/findBook/{name}")
public List<BookEntity> getBookByName(#PathVariable(value = "name")String bookName)
{
return bookRepository.findByBookName(bookName);
}
#GetMapping("/year/{year}")
public List<BookEntity> getBookByYear(#PathVariable(value = "year")Integer year)
{
return bookRepository.findByPublishYear(year);
}
#GetMapping("/publisher/{publisher}")
public List<BookEntity> getBookByPublisher(#PathVariable(value = "publisher")String publisher)
{
return bookRepository.findByPublisher(publisher);
}
#PostMapping("/create-book")
public BookEntity createBook (#RequestBody BookEntity book){
BookEntity savedBook = bookRepository.save(book);
return savedBook;
}
}
AuthorEntity:
package com.example.demo.entity;
import javax.persistence.*;
#Entity
#Table(name = "authors")
public class AuthorEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "surname",nullable = false)
private String surname;
#ManyToOne(fetch =FetchType.LAZY)
private BookEntity books;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
#Override
public String toString() {
return "AuthorEntity{" +
"id=" + id +
", name='" + name + '\'' +
", surname='" + surname + '\'' +
", books=" + books +
'}';
}
}
BookEntity:
package com.example.demo.entity;
import javax.persistence.*;
import java.util.List;
#Entity
#Table(name = "books")
public class BookEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer bookId;
#Column(name = "book_name", nullable = false)
private String bookName;
#Column(name = "publish_year",nullable = false)
private Integer publishYear;
#Column(name = "publisher",nullable = false)
private String publisher;
#OneToMany(targetEntity = AuthorEntity.class, cascade = CascadeType.ALL)
private List<AuthorEntity> authors;
public List<AuthorEntity> getAuthors() {
return authors;
}
public void setAuthors(List<AuthorEntity> authors) {
this.authors = authors;
}
public Integer getBookId() {
return bookId;
}
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public Integer getPublishYear() {
return publishYear;
}
public void setPublishYear(Integer publishYear) {
this.publishYear = publishYear;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
#Override
public String toString() {
return "BookEntity{" +
"bookId=" + bookId +
", bookName='" + bookName + '\'' +
", publishYear=" + publishYear +
", publisher='" + publisher + '\'' +
", authors=" + authors +
'}';
}
}
AuthorRepository:
package com.example.demo.repository;
import com.example.demo.entity.AuthorEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface AuthorRepository extends JpaRepository<AuthorEntity, Integer> {
List<AuthorEntity> findByName(String name);
}
BookRepository:
package com.example.demo.repository;
import com.example.demo.entity.BookEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface BookRepository extends JpaRepository<BookEntity, Integer> {
public List<BookEntity> findByBookName(String bookName);
public List<BookEntity> findByPublishYear(Integer year);
public List<BookEntity> findByPublisher(String publisher);
}

There are multiple way to do so , one approach is to use forEach and filter in java itself like
List<BookeEntity> books = getBooks();
books.forEach(e->{
List<AuthorEntity> al= e.getAuthors().stream().filter(ee->ee.getName().equals("Garyy")).collect(Collectors.toList());
e.setAuthors(al);
});

Your database design was wrong. Reality:
1 author wrote one or many books,
1 book wrote by one or many authors.
Therefore, you need an table author-book to convert relationship many-many to 2 relationships: one-many, many-one.
You can see https://www.stat.auckland.ac.nz/~paul/ItDT/HTML/node42.html section 5.6.3.2 Relationships

Related

Filter orders to a one day period - SpringBoot JPA MYSQL

I'm trying to retrieve a list of just the orders created from one day ago till today, and I can't manage to find any help about it, tried everything I found already.
Basically I need a getAllOrders(), but with filtered by that time period, one day....
How do I filter it ? I Found tons of tutorials on how to sort them descending or ascending, nothing else.
My order.java:
package com.proj.my.model;
import java.time.LocalDate;
import java.util.List;
import org.hibernate.annotations.CreationTimestamp;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.ToString;
#ToString
#Entity
#Table(name = "myorder")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties(value = {"createdAt"},
allowGetters = true)
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#OneToOne(cascade = CascadeType.MERGE)
#JoinColumn(name = "userId")
private User user;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, targetEntity = ShoppingCart.class)
#JoinColumn(name = "order_id")
private List<ShoppingCart> cartItems;
#CreationTimestamp
#Column(updatable = false, name = "createdAt")
private LocalDate createdAt;
public LocalDate getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDate createdAt) {
this.createdAt = createdAt;
}
public Order() {
}
public Order(User user, LocalDate createdAt, List<ShoppingCart> cartItems) {
this.user = user;
this.cartItems = cartItems;
this.createdAt = createdAt;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setCustomer(User user) {
this.user = user;
}
public List<ShoppingCart> getCartItems() {
return cartItems;
}
public void setCartItems(List<ShoppingCart> cartItems) {
this.cartItems = cartItems;
}
}
My orderservice.java
package com.proj.my.service;
import com.proj.my.model.Order;
import com.proj.my.model.CloudProduct;
import com.proj.my.model.ShoppingCart;
import com.proj.my.repository.OrderRepository;
import com.proj.my.repository.CloudProductRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
#Service
public class OrderService {
private OrderRepository orderRepository;
private CloudProductRepository cloudProductRepository;
public OrderService(OrderRepository orderRepository, CloudProductRepository cloudProductRepository) {
this.orderRepository = orderRepository;
this.cloudProductRepository = cloudProductRepository;
}
public Order getOrderDetail(int orderId) {
Optional<Order> order = this.orderRepository.findById(orderId);
return order.isPresent() ? order.get() : null;
}
/* #Query(value = "from order t where Date BETWEEN :yesterday AND :now")
public List<Order> getAllBetweenDates(#Param("yesterday")Date yesterday,#Param("now")Date localdate.now){
private LocalDate yesterday = now.minus(1, ChronoUnit.DAYS);
return orderRepository.findAll();
} */
public List<Order> getAllOrderDetail() {
return orderRepository.findAll();
}
public float getCartAmount(List<ShoppingCart> shoppingCartList) {
float totalCartAmount = 0f;
float singleCartAmount = 0f;
for (ShoppingCart cart : shoppingCartList) {
String cloudProductName = cart.getProductName();
Optional<CloudProduct> product = cloudProductRepository.findByProductName(cloudProductName);
if (product.isPresent()) {
CloudProduct cloudproduct = product.get();
singleCartAmount = cart.getQuantity() * cloudproduct.getpriceInEuros();
totalCartAmount = totalCartAmount + singleCartAmount;
cart.setProductId(cloudproduct.getProductId());
cart.setAmount(singleCartAmount);
cloudProductRepository.save(cloudproduct);
}
}
return totalCartAmount;
}
public Order saveOrder(Order order) {
return orderRepository.save(order);
}
}
My orderDTO.java
package com.proj.my.dto;
import com.proj.my.model.ShoppingCart;
import java.util.List;
public class OrderDTO {
private List<ShoppingCart> cartItems;
private String userEmail;
private String userName;
public OrderDTO() {
}
public OrderDTO(List<ShoppingCart> cartItems, String userEmail, String userName) {
this.cartItems = cartItems;
this.userEmail = userEmail;
this.userName = userName;
}
public List<ShoppingCart> getCartItems() {
return cartItems;
}
public void setCartItems(List<ShoppingCart> cartItems) {
this.cartItems = cartItems;
}
public String getuserEmail() {
return userEmail;
}
public void setuserEmail(String userEmail) {
this.userEmail = userEmail;
}
public String getuserName() {
return userName;
}
public void setuserName(String userName) {
this.userName = userName;
}
#Override
public String toString() {
return "OrderDTO{" +
", cartItems=" + cartItems +
", userEmail='" + userEmail + '\'' +
", userName='" + userName + '\'' +
'}';
}
}
My shoppingcart.java
package com.proj.my.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
/*#Data
#AllArgsConstructor
#RequiredArgsConstructor
#NoArgsConstructor
*/
#Entity
public class ShoppingCart {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private Integer productId;
private String productName;
private int quantity;
private float amount;
public ShoppingCart() {
}
public ShoppingCart(Integer productId, String productName, int quantity, float amount) {
this.productId = productId;
this.productName = productName;
this.quantity = quantity;
this.amount = amount;
}
public ShoppingCart(Integer productId, int quantity) {
this.productId = productId;
this.quantity = quantity;
}
public ShoppingCart(String productName, int quantity) {
this.productName = productName;
this.quantity = quantity;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public float getAmount() {
return amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
#Override
public String toString() {
return "ShoppingCart{" +
"id=" + id +
", productId=" + productId +
", productName='" + productName + '\'' +
", quantity=" + quantity +
", amount=" + amount +
'}';
}
}
And finally my orderController.java
package com.proj.my.controller;
import java.time.LocalDate;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.proj.my.dto.OrderDTO;
import com.proj.my.dto.ResponseOrderDTO;
import com.proj.my.model.Order;
import com.proj.my.model.User;
import com.proj.my.service.CloudProductService;
import com.proj.my.service.OrderService;
import com.proj.my.service.UserService;
#RestController
#RequestMapping("/api")
public class OrderController {
private OrderService orderService;
private CloudProductService cloudProductService;
private UserService userService;
public OrderController(OrderService orderService, CloudProductService cloudProductService, UserService userService) {
this.orderService = orderService;
this.cloudProductService = cloudProductService;
this.userService = userService;
}
#GetMapping(value = "/getOrder/{orderId}")
public ResponseEntity<Order> getOrderDetails(#PathVariable int orderId) {
Order order = orderService.getOrderDetail(orderId);
return ResponseEntity.ok(order);
}
#GetMapping(value = "/getOrder")
public List<Order> getAllOrderDetails() {
return orderService.getAllOrderDetail();
}
#PostMapping("/placeOrder")
public ResponseEntity<ResponseOrderDTO> placeOrder(#RequestBody OrderDTO orderDTO) {
ResponseOrderDTO responseOrderDTO = new ResponseOrderDTO();
float amount = orderService.getCartAmount(orderDTO.getCartItems());
User user = new User(orderDTO.getuserName(), orderDTO.getuserEmail());
Integer userIdFromDb = userService.isUserPresent(user);
if (userIdFromDb != null) {
user.setUserId(userIdFromDb);
}else{
user = userService.createUser(user);
}
LocalDate createdAt = LocalDate.now();
Order order = new Order(user, createdAt, orderDTO.getCartItems());
order = orderService.saveOrder(order);
responseOrderDTO.setAmount(amount);
responseOrderDTO.setDate(com.proj.my.util.DateUtil.getCurrentDateTime());
responseOrderDTO.setOrderId(order.getId());
return ResponseEntity.ok(responseOrderDTO);
}}
You can add method in OrderRepository interface
public List<Order> findByCreatedAtBetween(LocalDate d1, LocalDate d2)
and call it
orderRepository.findByCreatedAtBetween(today.minusDays(1),today);
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.details

Class sorting JSON by ID instead of highest value

I'm doing a vote counting system, the winner is the one who has more than 3 votes, however, I'm facing the following problem. When there is more than one place with 3 votes, instead of my JSON returning the one with the most votes, it always returns the one with more than 3 votes ordered by ID.
That is, if the restaurant with ID 1 has 3 votes, and the restaurant with ID 2 has 10 votes, the restaurant with ID 1 ends up appearing on the route /restaurants/winner despite not being the most voted, is there any way I can make the most voted show up?
e.g: return from /restaurants/winner route
{
"id": 1,
"restaurant": "Burger King",
"address": "Av. Ipiranga, 1600",
"website": "https://www.burgerking.com.br/",
"description": "Rede de fast-food famosa com hambúrgueres grelhados, batata frita e milk-shakes.",
"count": 3
}
While McDonalds has 5 votes
{
"id": 2,
"restaurant": "McDonalds",
"address": "Av. Ipiranga, 5200",
"website": "https://www.mcdonalds.com.br/",
"description": "Rede de fast-food tradicional conhecida por ter ótimos hambúrgueres e batatas fritas.",
"count": 5
}
Here are the classes that I'm using:
Restaurant.java
package com.dbserver.restaurantes.entities;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#Table(name = "db_restaurants")
public class Restaurant {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String restaurant;
private String address;
private String website;
private String description;
private Integer count;
#JsonIgnore
#OneToMany(mappedBy = "id.restaurant")
private Set<Vote> votes = new HashSet<>();
public Restaurant() {
}
public Restaurant(Long id, String restaurant, String address, String website, String description, Integer count) {
this.id = id;
this.restaurant = restaurant;
this.address = address;
this.website = website;
this.description = description;
this.count = count;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRestaurant() {
return restaurant;
}
public void setRestaurant(String restaurant) {
this.restaurant = restaurant;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public Set<Vote> getVotes() {
return votes;
}
}
RestaurantDTO.java
package com.dbserver.restaurantes.dto;
import com.dbserver.restaurantes.entities.Restaurant;
public class RestaurantDTO {
private Long id;
private String restaurant;
private String address;
private String website;
private String description;
private Integer count;
public RestaurantDTO() {
}
public RestaurantDTO(Long id, String restaurant, String address, String website, String description, Integer count) {
this.id = id;
this.restaurant = restaurant;
this.address = address;
this.website = website;
this.description = description;
this.count = count;
}
public RestaurantDTO(Restaurant restaurantDTO) {
id = restaurantDTO.getId();
restaurant = restaurantDTO.getRestaurant();
address = restaurantDTO.getAddress();
website = restaurantDTO.getWebsite();
description = restaurantDTO.getDescription();
count = restaurantDTO.getCount();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRestaurant() {
return restaurant;
}
public void setRestaurant(String restaurant) {
this.restaurant = restaurant;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
RestaurantServices.java
package com.dbserver.restaurantes.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.dbserver.restaurantes.dto.RestaurantDTO;
import com.dbserver.restaurantes.entities.Restaurant;
import com.dbserver.restaurantes.exceptions.NotFoundException;
import com.dbserver.restaurantes.repositories.RestaurantRepository;
#Service
public class RestaurantServices {
#Autowired
private RestaurantRepository repository;
#Transactional(readOnly = true)
public Page<RestaurantDTO> findAll(Pageable pageable) {
Page<Restaurant> result = repository.findAll(pageable);
Page<RestaurantDTO> page = result.map(x -> new RestaurantDTO(x));
return page;
}
#Transactional(readOnly = true)
public RestaurantDTO findById(Long id) {
Restaurant result = repository.findById(id).get();
RestaurantDTO dto = new RestaurantDTO(result);
return dto;
}
#Transactional(readOnly = true)
public Restaurant findWinner(Integer count) {
List<Restaurant> restaurants = repository.findAll();
for (Restaurant restaurant : restaurants) {
// Hibernate.initialize(restaurant.getCount());
if (restaurant.getCount() >= 3) {
return restaurant;
}
}
throw new NotFoundException(
"Nenhum restaurante ganhou a votação, é necessário um total de 3 votos para ter um restaurante vencedor.");
}
#Transactional
public Restaurant addRestaurant(Restaurant newRestaurant) {
return repository.saveAndFlush(newRestaurant);
}
}
RestaurantRepository.java
package com.dbserver.restaurantes.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import com.dbserver.restaurantes.entities.Restaurant;
public interface RestaurantRepository extends JpaRepository<Restaurant, Long> {
}
RestaurantController.java
package com.dbserver.restaurantes.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.dbserver.restaurantes.dto.RestaurantDTO;
import com.dbserver.restaurantes.entities.Restaurant;
import com.dbserver.restaurantes.services.RestaurantServices;
#RestController
#RequestMapping(value = "/restaurants")
public class RestaurantController {
#Autowired
private RestaurantServices service;
#GetMapping
public Page<RestaurantDTO> findAll(Pageable pageable) {
return service.findAll(pageable);
}
#GetMapping(value = "/{id}")
public RestaurantDTO findById(#PathVariable Long id) {
return service.findById(id);
}
#GetMapping(value = "/winner")
public Restaurant findWinner(Integer count) {
return service.findWinner(count);
};
#PostMapping
public Restaurant addRestaurant(#RequestBody Restaurant newRestaurant) {
return service.addRestaurant(newRestaurant);
}
}
You have to check the top value as well. So You need to add your own query for that. Here is the code
public interface RestaurantRepository extends JpaRepository<Restaurant, Long>
{
Optional<Restaurant> findFirstByCountGreaterThanEqualOrderByCountDesc (Integer count);
}
and Use that inside your method
#Transactional(readOnly = true)
public Restaurant findWinner(Integer count) throws NotFoundException
{
Optional<Restaurant> data = repository.findFirstByCountGreaterThanEqualOrderByCountDesc(3);
if (data.isPresent())
{
return data.get();
}
throw new NotFoundException("Nenhum restaurante ganhou a votação, é necessário um total de 3 votos para ter um restaurante vencedor.");
}
You can use native queries as well.

Creating a banking API and have customer have an address. How would I do that?

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String street_number;
private String street_name;
private String city;
private String state;
private String zip;
public Address() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStreet_number() {
return street_number;
}
public void setStreet_number(String street_number) {
this.street_number = street_number;
}
public String getStreet_name() {
return street_name;
}
public void setStreet_name(String street_name) {
this.street_name = street_name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
}
package com.bankingapplicationmain.bankingapplicationmain.models;
import javax.persistence.*;
import java.util.Set;
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String first_Name;
private String last_Name;
#OneToMany
private Set<Address> addresses;
public Customer() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirst_Name() {
return first_Name;
}
public void setFirst_Name(String first_Name) {
this.first_Name = first_Name;
}
public String getLast_Name() {
return last_Name;
}
public void setLast_Name(String last_Name) {
this.last_Name = last_Name;
}
}
So far, I tried to use "many-to-one", "many-to-many", but I guess I am still not sure how these work! My create, delete, methods are working fine, but all customers are missing addresses when I try to fetch them.
What I posted:
{
"id": 1,
"first_name": "Leon",
"last_name": "Hunter",
"address": {
"street_number": "902",
"street_name": "Walker Road",
"city": "Clearfield",
"state": "Pennsylvania",
"zip": "16830"
}
}
VS What I am getting:
{
"id": 1,
"first_name": "Leon",
"last_name": "Hunter"
Any help is really appreciated!
Edit:
import com.bankingapplicationmain.bankingapplicationmain.models.Customer;
import com.bankingapplicationmain.bankingapplicationmain.services.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
#RestController
#RequestMapping("/customer")
public class CustomerController {
#Autowired
CustomerService customerService;
//get all customers
#GetMapping
public ResponseEntity<List<Customer>> getAllCustomers(){
return customerService.getAllCustomers();
}
//get customer by id
#GetMapping("/{id}")
public ResponseEntity<Customer> getCustomerById(#PathVariable Long id){
return customerService.getCustomerById(id);
}
//create customer
#PostMapping
public ResponseEntity<?> createCustomer(#Valid #RequestBody Customer customer) {
return customerService.createCustomer(customer);
}
//edit customer
#PutMapping("/{id}")
public ResponseEntity<?> updateCustomer(#PathVariable Long id, #Valid #RequestBody Customer customer){
return customerService.updateCustomer(customer, id);
}
}
package com.bankingapplicationmain.bankingapplicationmain.services;
import com.bankingapplicationmain.bankingapplicationmain.exceptions.CustomerNotFoundException;
import com.bankingapplicationmain.bankingapplicationmain.models.Customer;
import com.bankingapplicationmain.bankingapplicationmain.repositories.CustomerRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import java.net.URI;
import java.util.List;
import java.util.Optional;
#Service
public class CustomerService {
private CustomerRepository customerRepository;
private static final Logger logger = LoggerFactory.getLogger(CustomerService.class);
#Autowired
public CustomerService(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
protected void verifyCustomer(Long customerId) throws CustomerNotFoundException {
Optional<Customer> customer = customerRepository.findById(customerId);
if(customer.isEmpty()) {
throw new CustomerNotFoundException("Customer with id " + customerId + " not found");
}
}
// Get all customers
public ResponseEntity<List<Customer>> getAllCustomers() {
logger.info("Customer(s) found.");
return new ResponseEntity<>(customerRepository.findAll(), HttpStatus.OK);
}
//get customer by id
public ResponseEntity<Customer> getCustomerById(Long customerId) {
if (customerRepository.findById(customerId).isPresent()) {
logger.info("Customer found.");
customerRepository.findById(customerId);
}
throw new CustomerNotFoundException("Customer with id " + customerId + " not found");
}
public ResponseEntity<?> createCustomer(Customer customer){
logger.info("Customer created.");
customerRepository.save(customer);
HttpHeaders responseHeaders = new HttpHeaders();
URI newCustomerUri = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(customer.getId())
.toUri();
responseHeaders.setLocation(newCustomerUri);
return new ResponseEntity<>(null, responseHeaders, HttpStatus.CREATED);
}
public ResponseEntity<?> updateCustomer(Customer customer, Long customerId) {
verifyCustomer(customerId);
logger.info("Customer info updated.");
customerRepository.save(customer);
return new ResponseEntity<>(HttpStatus.OK);
}
}
As requested from others, I have added my service and controller classes as well. Maybe I am doing something wrong in here too.
The example data that you posted would work for a ManyToOne or a OneToOne relationship, but for the code that you posted, you would need something like this:
{
"id": 1,
"first_name": "Leon",
"last_name": "Hunter",
"addresses": [{
"street_number": "902",
"street_name": "Walker Road",
"city": "Clearfield",
"state": "Pennsylvania",
"zip": "16830"
}]
}
I would recommend a one-to-one relationship for the address, this way all data for individual clients will be kept separate.
For example, if you have mum, dad and kid all linked to one address and the kid moves out, you might change their address and change the address for the parents which is unwanted behavior.
As for the Address not showing, what code are you using to retrieve the data?
I suspect because it isn't a primitive value(string) you may need to add a method to combine all the address data into a single string

Why postman indicated 404 not found

I'm trying to return data from database but this error has occurred I don't know the error is 404 this is my code :
http://localhost:8085/exercices
my Exercice class
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "exercice")
public class exercices implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long idExercice;
private String nomExercice;
private String LinkExercice;
#ManyToOne
private patient patient;
public exercices(Long idExercice, String nomExercice, String linkExercice) {
this.idExercice = idExercice;
this.nomExercice = nomExercice;
this.LinkExercice = linkExercice;
this.patient = new patient();
}
public exercices(String nomExercice, String linkExercice) {
this.nomExercice = nomExercice;
LinkExercice = linkExercice;
}
public Long getIdExercice() {
return idExercice;
}
public void setIdExercice(Long idExercice) {
this.idExercice = idExercice;
}
public String getNomExercice() {
return nomExercice;
}
public void setNomExercice(String nomExercice) {
this.nomExercice = nomExercice;
}
public String getLinkExercice() {
return LinkExercice;
}
public void setLinkExercice(String linkExercice) {
LinkExercice = linkExercice;
}
#Override
public String toString() {
return "exercices [LinkExercice=" + LinkExercice + ", idExercice=" + idExercice + ", nomExercice=" + nomExercice
+ "]";
}
}
ExerciceController
import java.util.List;
import org.apache.catalina.connector.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import healthP.Health.Progress.model.exercices;
import healthP.Health.Progress.service.ExerciceService;
#RestController
#RequestMapping()
public class ExerciceController {
#Autowired
private final ExerciceService exserv;
public ExerciceController(ExerciceService exserv) {
this.exserv = exserv;
}
#GetMapping("/exercices")
public ResponseEntity<List<exercices>> getAllExercices() {
List<exercices> ex = this.exserv.findAllExercices();
return new ResponseEntity<>(ex, HttpStatus.OK);
}
}
ExerciceService
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import healthP.Health.Progress.model.exercices;
import healthP.Health.Progress.repo.ExercicesRepo;
#Service
public class ExerciceService {
private final ExercicesRepo ExRepo;
#Autowired
public ExerciceService(ExercicesRepo ExRepo) {
this.ExRepo = ExRepo;
}
public List<exercices> findAllExercices() {
return this.ExRepo.findAll();
}
}
interface
import org.springframework.data.jpa.repository.JpaRepository;
import healthP.Health.Progress.model.exercices;
public interface ExercicesRepo extends JpaRepository<exercices, Long> {
}
and this is patient class because I want also check if the relation between two classes are correcte and spacially in the constructeur of exercice class.
package healthP.Health.Progress.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
//import org.hibernate.annotations.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
#Entity
#Table(name = "patient")
// #Table(name = patient.TABLE_NAME)
public class patient implements Serializable {
// public static final String TABLE_NAME="PATIENT";
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int score;
#Column(nullable = false, updatable = false)
private Long id;
private String name;
private String email;
private String password;
#Column(nullable = false, updatable = false)
private String codePatient;
public patient() {
}
public patient(String codep, String name, String email, String password) {
this.codePatient = codep;
this.name = name;
this.email = email;
this.password = password;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCodePatient() {
return this.codePatient;
}
public void setCodePatient(String codePatient) {
this.codePatient = codePatient;
}
public void setScore(int score) {
this.score = score;
}
public int getScore() {
return this.score;
}
#Override
public String toString() {
return "{" + " id='" + getId() + "'" + ", name='" + getName() + "'" + ", email='" + getEmail() + "'"
+ ", password='" + getPassword() + "'" + "}";
}
}```
add api-path to requestmapping of ExerciceController , so it becomes
#RequestMapping("/api")
public class ExerciceController {
EDIT:
You need to add default constructor to excercises entity
public exercices(){}
now you can access it as http://localhost:8085/api/exercices
PS: unrelated to question, use singular class name for entity excercise instead of excercises
You can make little changes in your code and follow any of below approach:
1- Remove #RequestMapping()
You can access endpoint : http://localhost:8085/exercices
2- If you want to manage the api versioning then use #RequestMapping("/api/v1")
You can use endpoint: http://localhost:8085/api/v1/exercices

how to fetch all data from database using one to many relation hibernate query

I have two table Parent table is Credit in that table only one row of data is there and another one is child table Debit that contains multiple row of data. how to fetch data from two table which has to match id of parent class and child class and no duplicate is shown from parent class.
I have try with (from Credit,debit) but that can display with duplicate and not properly data is shown based on id.
package com.rojmat.entity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.springframework.core.annotation.Order;
#Entity
#Table(name="credit")
public class Credit extends BaseEntity{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private long cid;
#Column #Order
private long openingbalance;
#Column
private Date date;
#Column #Order
private long debittotal;
#Column #Order
private long drawertotal;
#Column #Order
private long debittotalplusdrawertotal;
#Column #Order
private long todaybusiness;
#OneToMany(cascade={CascadeType.ALL})
#JoinTable(name="credit_debit",
joinColumns=#JoinColumn(name="c_id"),
inverseJoinColumns=#JoinColumn(name="d_id"))
/*#JoinColumn(name="cid", referencedColumnName="cid")*/
private List<Debit> debits = new ArrayList<Debit>(Arrays.asList());
public Credit() {
}
public Credit(long cid, long openingbalance, Date date, long debittotal, long drawertotal,
long debittotalplusdrawertotal, long todaybusiness, List<Debit> debits) {
super();
this.cid = cid;
this.openingbalance = openingbalance;
this.date = date;
this.debittotal = debittotal;
this.drawertotal = drawertotal;
this.debittotalplusdrawertotal = debittotalplusdrawertotal;
this.todaybusiness = todaybusiness;
this.debits = debits;
}
public long getCid() {
return cid;
}
public void setCid(long cid) {
this.cid = cid;
}
public long getOpeningbalance() {
return openingbalance;
}
public void setOpeningbalance(long openingbalance) {
this.openingbalance = openingbalance;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public long getDebittotal() {
return debittotal;
}
public void setDebittotal(long debittotal) {
this.debittotal = debittotal;
}
public long getDrawertotal() {
return drawertotal;
}
public void setDrawertotal(long drawertotal) {
this.drawertotal = drawertotal;
}
public long getDebittotalplusdrawertotal() {
return debittotalplusdrawertotal;
}
public void setDebittotalplusdrawertotal(long debittotalplusdrawertotal) {
this.debittotalplusdrawertotal = debittotalplusdrawertotal;
}
public long getTodaybusiness() {
return todaybusiness;
}
public void setTodaybusiness(long todaybusiness) {
this.todaybusiness = todaybusiness;
}
public List<Debit> getDebit() {
return debits;
}
public void setDebit(List<Debit> debit) {
this.debits = debits;
}
/*#Override
public String toString() {
return "Credit [cid=" + cid + ", openingbalance =" + openingbalance + ", date=" + date + ", debittotal= " + debittotal + ", debittotalplusdrawertotal=" + debittotalplusdrawertotal + ", todaybusiness=" + todaybusiness + "]";
}*/
}
package com.rojmat.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="debit")
public class Debit {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private long did;
#Column
private String amount;
#Column
private String description;
public Debit() {
}
public Debit(String amount, String description) {
super();
this.amount = amount;
this.description = description;
}
public long getDid() {
return did;
}
public void setDid(long did) {
this.did = did;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return "Debit [did=" + did + ", amount =" + amount + ", description=" + description + "]";
}
}
1.CreditDaoImpl.java
package com.rojmat.daoImpl;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.rojmat.dao.CreditDao;
import com.rojmat.entity.Credit;
#Repository
public class CreditDaoImpl implements CreditDao{
#Autowired
private SessionFactory sessionFactory;
#Override
public void addCreditDebit(Credit credit) {
try {
sessionFactory.getCurrentSession().saveOrUpdate(credit);
} catch(Exception e) {
e.printStackTrace();
}
}
#Override
public void deleteCreditDebit(int cid) {
/*Credit credit = (Credit)sessionFactory.getCurrentSession().createQuery("from Credit as c LEFT JOIN FETCH c.Debit where c.cid="+cid).uniqueResult();
List<Debit> debits = credit.getDebit();
sessionFactory.getCurrentSession().delete(credit);
debits.forEach((debit) -> {
sessionFactory.getCurrentSession().delete(debit);
});*/
}
#SuppressWarnings("unchecked")
#Override
public List<Credit> getAllCreditDebit() {
List<Credit> credit = sessionFactory.getCurrentSession().createQuery("from Credit,Debit").list();
return credit;
}
}
try this example: you put "distinct" before the property you do not want to be duplicated
//SQL query
select distinct credit.idCredit as idCredit from Credit credit Left Join Debit debit on credit.idCredit= debit.idCredit
//HQL query
#Entity(name = "Credit")
#Table(name = "Credit")
public class Credit{
//if you put #Id --> HQL Query "select credit from Credit credit"
#Column(name = "idCredit")
private Long idCredit;
#Column(name = "label")
private String label;
#OneToMany
#JoinColumns({#JoinColumn(name = "idCredit" ,referencedColumnName = "idCredit")})
List<Debit> debits;
...
}
public class Debit{
....
#Column(name = "idCredit")
private Long idCredit;
...
}
Query query = getSession().createQuery("select distinct credit.idCredit as idCredit, credit.label as label, credit.debits as debits from Credit credit ");
query.setResultTransformer(Transformers.aliasToBean(Credit.class));
return query.list();
package com.rojmat.entity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.springframework.core.annotation.Order;
#Entity
#Table(name="credit")
public class Credit extends BaseEntity{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private long cid;
#Column #Order
private long openingbalance;
#Column
private Date date;
#Column #Order
private long debittotal;
#Column #Order
private long drawertotal;
#Column #Order
private long debittotalplusdrawertotal;
#Column #Order
private long todaybusiness;
#OneToMany(cascade={CascadeType.ALL})
#JoinTable(name="credit_debit",
joinColumns=#JoinColumn(name="c_id"),
inverseJoinColumns=#JoinColumn(name="d_id"))
/*#JoinColumn(name="cid", referencedColumnName="cid")*/
private List<Debit> debits = new ArrayList<Debit>(Arrays.asList());
public Credit() {
}
public Credit(long cid, long openingbalance, Date date, long debittotal, long drawertotal,
long debittotalplusdrawertotal, long todaybusiness, List<Debit> debits) {
super();
this.cid = cid;
this.openingbalance = openingbalance;
this.date = date;
this.debittotal = debittotal;
this.drawertotal = drawertotal;
this.debittotalplusdrawertotal = debittotalplusdrawertotal;
this.todaybusiness = todaybusiness;
this.debits = debits;
}
public long getCid() {
return cid;
}
public void setCid(long cid) {
this.cid = cid;
}
public long getOpeningbalance() {
return openingbalance;
}
public void setOpeningbalance(long openingbalance) {
this.openingbalance = openingbalance;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public long getDebittotal() {
return debittotal;
}
public void setDebittotal(long debittotal) {
this.debittotal = debittotal;
}
public long getDrawertotal() {
return drawertotal;
}
public void setDrawertotal(long drawertotal) {
this.drawertotal = drawertotal;
}
public long getDebittotalplusdrawertotal() {
return debittotalplusdrawertotal;
}
public void setDebittotalplusdrawertotal(long debittotalplusdrawertotal) {
this.debittotalplusdrawertotal = debittotalplusdrawertotal;
}
public long getTodaybusiness() {
return todaybusiness;
}
public void setTodaybusiness(long todaybusiness) {
this.todaybusiness = todaybusiness;
}
public List<Debit> getDebit() {
return debits;
}
public void setDebit(List<Debit> debit) {
this.debits = debits;
}
/*#Override
public String toString() {
return "Credit [cid=" + cid + ", openingbalance =" + openingbalance + ", date=" + date + ", debittotal= " + debittotal + ", debittotalplusdrawertotal=" + debittotalplusdrawertotal + ", todaybusiness=" + todaybusiness + "]";
}*/
}
package com.rojmat.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="debit")
public class Debit {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private long did;
#Column
private String amount;
#Column
private String description;
public Debit() {
}
public Debit(String amount, String description) {
super();
this.amount = amount;
this.description = description;
}
public long getDid() {
return did;
}
public void setDid(long did) {
this.did = did;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
/*#Override
public String toString() {
return "Debit [did=" + did + ", amount =" + amount + ", description=" + description + "]";
}*/
}

Categories