Gradle/Hibernate/Maven Annotations Foreign Key Creation - mysql

I am currently working on a Gradle project that uses Maven/Hibernate. The program plugs-in to a MySQL database. I am generating the tables via the Java class. IE when I run it the first time it creates the tables.
My issue is that I am currently receiving this error "(errno: 150 "Foreign key constraint is incorrectly formed")". I am convinced it has to do with my annotations relating Staff and Tickets.
Staff class:
import java.io.Serializable;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "Staff")
public class Staff implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int staffId;
private String badgeCode;
private String firstName;
private String lastName;
private String email;
private String phone;
private String skillLevel;
private String status;
#OneToMany(mappedBy = "ticketId", fetch = FetchType.EAGER)
private List<Ticket> tickets;
Ticket Class:
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "Ticket")
public class Ticket implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int ticketId;
private int customerId;
#ManyToOne
#JoinColumn(name = "STAFF_ID")
private Staff helpStaff;
private String problemDesc;
private String resolution;
//(year, month, date, hrs, min, sec)
private Date createdDate;
private Date resolvedDate;
private String status;
So a Ticket has one Staff tied to it, which in my mind means ManyToOne. Whereas a Staff has many tickets, which is OneToMany. I was originally able to get the findAll() hibernate query to work, but it was returning the object ID for the Ticket field rather than any information about the ticket.
My questions are: What is causing the foreign key issue. Why is a tickets field not being created in the Staff table for the List and what is causing the object id to be returned rather than any real data?

Answer given to me via another source. User g051051 on Reddit helped me out.
In the Staff class:
#OneToMany(mappedBy="helpStaff", fetch=FetchType.EAGER)
private List<Ticket> tickets;
In the Ticket class:
#ManyToOne
#JoinColumn(name="staffId", nullable=false)
public Staff getHelpStaff() { return helpStaff; }
So the list of Tickets will be determined by the helpStaff property of the Ticket class. The Ticket class will create an association column called staffId that will use the primary key of the Staff entity.

Related

How to delete/update by querying on JPA interface?

The Item table has Many to One relationship with supplier table.
If i delete supplier table row data by Id, its not deleting the row.
The Item table has many rows with same supplier Id. If i delete in supplier table with id, the item table supplier column data /id should be deleted.
Thanks in advance
Item
package com.ingroinfo.ubm.entity;
import java.util.Date;
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.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "master_item")
#SequenceGenerator(name = "item_sequence", initialValue = 201, allocationSize = 10000)
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "branch_sequence")
private Long itemId;
private String itemName;
private String itemImage;
private String itemStatus;
private String unitOfMeasure;
private String remarks;
private String units;
#ManyToOne
#JoinColumn(name = "category_id")
private Category category;
#ManyToOne
#JoinColumn(name = "supplier_id")
private Supplier supplier;
#ManyToOne
#JoinColumn(name = "brand_id")
private Brand brand;
#ManyToOne
#JoinColumn(name = "publisher_id")
private BrandPublisher publisher;
#ManyToOne
#JoinColumn(name = "hsn_id")
private HsnCode hsnCode;
#Column(name = "date_created")
#CreationTimestamp
private Date dateCreated;
#Column(name = "last_updated")
#UpdateTimestamp
private Date lastUpdated;
}
ItemRepository
package com.ingroinfo.ubm.dao;
import javax.transaction.Transactional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.ingroinfo.ubm.entity.Item;
#Repository
#Transactional
public interface ItemRepository extends JpaRepository<Item, Long> {
Item findByItemId(Long id);
#Modifying
#Query("UPDATE Item i SET i.supplier= :val WHERE i.supplier = :id")
void deleteSupplierId(#Param("val") String val, #Param("id") Long id);
}
MasterService
void deleteItemSupplierId(String val, Long id);
MasterServiceImpl
#Override
public void deleteItemSupplierId(String val, Long id) {
itemRepository.deleteSupplierId(val, id);
}
MasterController
#GetMapping("/supplier/delete")
public String deleteSupplier(#RequestParam Long supplierId) {
masterService.deleteItemSupplierId(null, supplierId);
masterService.deleteBySupplierId(supplierId);
return "redirect:/master/supplier/list?supplierDeleted";
}
You can do that by using cascade types, for example
#OneToMany(cascade = CascadeType.REMOVE)

Why does my method with #Query to perform a PostMapping or save me generate an error type: java.sql.SQLException: Not a navigable ResultSet

I am trying to perform a CRUD with JPA and mysql through #Query, for this in my database I have a stored procedure that registers me in a table.
When I hit the service from the postman, it generates a 500 Internal Server Error and in the console of my IDEA it responds with the error:
java.sql.SQLException: Create breakpoint Not a navigable ResultSet.
I leave here the complete flow of what I am doing, from the database to the controller
CREATE DEFINER=`root`#`localhost` PROCEDURE `insert_ticket_procedure`( IN codigo VARCHAR(45),
IN user_id int,
IN cost float,
IN seats_amount int,
IN laggage_amount int,
IN total_seats_amount int,
IN driver_id int
)
BEGIN
INSERT INTO tickets (code, user_id, cost, seats_amount, laggage_amount, total_seats_amount, driver_id)
values(codigo, user_id, cost, seats_amount, laggage_amount, total_seats_amount, driver_id );
END
In my application I have two DTOs:
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Getter
#Setter
#Entity
public class Tickets{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer ticket_id;
private String code;
private Integer driver_id;
private Integer user_id;
private Float cost;
private Integer seats_amount;
private Integer laggage_amount;
private Integer total_seats_amount;
}
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.List;
#Getter
#Setter
#Entity
public class Users {
#Id
private Integer user_id;
private String complete_name;
private String mail;
private String password;
private String number;
#OneToMany(cascade={CascadeType.ALL})
#JoinColumn(name="user_id")
private List<Tickets> ticketsList;
}
The relationship is that a user can have many tickets
import com.terminals.demo.dto.Tickets;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
#Repository
public interface TicketsRepository extends JpaRepository<Tickets, Integer> {
#Query(value = "{call insert_ticket_procedure(:code, :driver_id, :user_id, :cost, :seats_amount, :laggage_amount, :total_seats_amount)}", nativeQuery = true)
void insertTickets(
#Param("code")String code,
#Param("driver_id")Integer driver_id,
#Param("user_id")Integer user_id,
#Param("cost")Float cost,
#Param("seats_amount")Integer seats_amount,
#Param("laggage_amount")Integer laggage_amount,
#Param("total_seats_amount")Integer total_seats_amount
);
}
This repository is called by a implementation or "service" that implements an interface
import com.terminals.demo.Repository.TicketsRepository;
import com.terminals.demo.dto.Tickets;
import com.terminals.demo.interfaces.ITickersImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class TicketsImpl implements ITickersImpl {
#Autowired
private TicketsRepository ticketsRepository;
#Override
public void saveTickets(Tickets tickets) {
ticketsRepository.insertTickets(tickets.getCode(),tickets.getDriver_id(),tickets.getUser_id(), tickets.getCost(),tickets.getSeats_amount(), tickets.getLaggage_amount(),tickets.getTotal_seats_amount());
}
}
And the controller:
import com.terminals.demo.dto.Tickets;
import com.terminals.demo.interfaces.ITickersImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;
#RestController
#RequestMapping("/terminals")
public class TicketsController {
#Autowired
ITickersImpl iTickers;
#PostMapping("/addticket")
public ResponseEntity<?> insertTicket(#RequestBody Tickets tickets){
iTickers.saveTickets(tickets);
return new ResponseEntity<>("Registro Exitoso", HttpStatus.CREATED);
}
}
My request:
"code": "sdf23f",
"driver_id": 1,
"user_id": 2,
"cost": 23.0,
"seats_amount": 20,
"laggage_amount": 2,
"total_seats_amount": 2
}```

Need to get Spring to return MySQL View data back to REACT front end

I am trying to get my Spring MySQL backend to return a mutli table VIEW (not a single table) thru AXIOS to my REACT front end.
I am testing my Backend with POSTMAN (http://localhost:8080/api/v1/cpysiteassetview)
I get an error messages from SPRING and a long error message from POSTMAN (below).
I am close, but going wrong somewhere and I hope someone more familiar with this can shed some light and explain where I am going wrong.
Here is the VIEW\MODEL\REPOSITORY\CONTROLLER.
...
CREATE
ALGORITHM = UNDEFINED
DEFINER = `root`#`localhost`
SQL SECURITY DEFINER
VIEW `cpysiteasset` AS
SELECT
`cpymaster`.`cpymasterid` AS `cpymasterid`,
`cpymaster`.`cpymastercode` AS `cpymastercode`,
`cpymaster`.`cpymastername` AS `cpymastername`,
`sitemaster`.`sitemasterid` AS `sitemasterid`,
`sitemaster`.`sitemastercode` AS `sitemastercode`,
`sitemaster`.`sitemastername` AS `sitemastername`,
`assets`.`assetsid` AS `assetsid`,
`assets`.`assetsidentifier` AS `assetsidentifier`,
`assets`.`assetsname` AS `assetsname`
FROM
((`cpymaster`
JOIN `sitemaster` ON = `cpymaster`.`cpymasterid`)))
JOIN `assets` ON ((`assets`.`sitemaster_sitemasterid` = `sitemaster`.`sitemasterid`)))
ORDER BY `sitemaster`.`sitemastercode` , `assets`.`assetsidentifier`
//MODEL
package net.javaguides.springboot.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Immutable;
#Entity
#Immutable
#Table(name = "`cpysiteassetview`")
public class CpySiteAssetView {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private int cpymasterid;
private String cpymastercode;
private String cpymastername;
private int sitemasterid;
private String sitemastercode;
private String sitemastername;
private int assetsid;
private String assetsidentifier;
private String assetsname;
#Column(name = "cpymasterid")
public int getCpymasterid() {
return cpymasterid;
}
#Column(name = "cpymastercode")
public String getCpymastercode() {
return cpymastercode;
}
#Column(name = "cpymastername")
public String getCpymastername() {
return cpymastername;
}
#Column(name = "sitemasterid")
public int getSitemasterid() {
return sitemasterid;
}
#Column(name = "sitemastercode")
public String getSitemastercode() {
return sitemastercode;
}
#Column(name = "sitemastername")
public String getSitemastername() {
return sitemastername;
}
#Column(name = "assetsid")
public int getAssetsid() {
return assetsid;
}
#Column(name = "assetsidentifier")
public String getAssetsidentifier() {
return assetsidentifier;
}
#Column(name = "assetsname")
public String getAssetsname() {
return assetsname;
}
}
//Repository
package net.javaguides.springboot.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import net.javaguides.springboot.model.CpySiteAssetView;
#Repository
public interface CpySiteAssetViewRepository1 extends JpaRepository<CpySiteAssetView, Long>{
public List<CpySiteAssetView> findAll();
}
//Controller
package net.javaguides.springboot.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import net.javaguides.springboot.model.CpySiteAssetView;
import net.javaguides.springboot.repository.CpySiteAssetViewRepository1;
#CrossOrigin(origins = "http://localhost:3000")
#RestController
#RequestMapping("/api/v1/")
public class CpySiteAssetViewController {
#Autowired
private CpySiteAssetViewRepository1 cpySiteAssetViewRepository1;
//get all
#GetMapping("/cpysiteassetview")
public List<CpySiteAssetView> getAllCpySiteAssetView(){
return cpySiteAssetViewRepository1.findAll();
}
}
...
Error Message from Spring:
java.sql.SQLSyntaxErrorException: Unknown column 'cpysiteass0_.id' in 'field list'
Error Message from Postman (first part):
"error": "Internal Server Error",
"trace": "org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:259)\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)\r\n\tat org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)\r\n\tat org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)\r\n\tat org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)\r\n\tat org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(Per
OK..commented out //private long id;
and now it works !!!!!

Spring boot application executes without any error but not creating any tables in the backend

I have created a spring boot and RestAPI application project. Everything runs and executes but it is not creating any table in the backend (MySQL). It is not showing any error in the console too. I am new to spring boot and APIs.
Below is the code in my:
application.properties :
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/EjikeDB?createDatabaseIfNotExist=true&&autoReconnect=true&verifyServerCertificate=false&useSSL=false&requireSSL=false serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=MacRoot31
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.datasource.initialization-mode=always
########### SMTP Email Properties ###################
spring.mail.host=smtp.mailtrap.io
spring.mail.port=465
spring.mail.username=f26e44090838e5
spring.mail.password=b2a684f17dbfc2
spring.mail.protocol=smtp
############ JWT Properties #####################
jwt.expiration.time=90000
and
User.java :
import java.util.List;
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 javax.validation.constraints.NotBlank;
import java.time.Instant;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//#EnableAutoConfiguration
#EntityScan
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "MarketplaceUser")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int userid;
private String firstname;
private String lastname;
#NotBlank(message = "Username is required")
private String userName;
#NotBlank(message = "Email is required")
private String email;
#NotBlank(message = "Password is required")
private String password;
private String phoneNumber;
private String country;
private String provinceState;
private String city;
private String street;
#NotBlank(message = "Postcode is required")
private String postalCode;
private String roles;
#OneToMany(mappedBy = "user")
private List<Product> product;
private Instant created;
private boolean enabled;
}
I tried adding the spring.jpa.hibernate.ddl-auto=update
and
spring.jpa.hibernate.ddl-auto=create both
aswell as
createDatabaseIfNotExist=true&&autoReconnect=true&verifyServerCertificate=false&useSSL=false&requireSSL=false to my application.properties file.
But nothing changed. And the main issue being there's no error displayed in the console.
This is the project structure. If in case there's any error in this.
Recently I had same issue that spring wasn't creating mysql tables, but this line in application.properties fixed it
spring.jpa.hibernate.ddl-auto = create
Is your entity class in the same package or a relative one where you have the main spring class (the one you add the #EnableAutoConfiguration)? If not, spring probably won't find it. And this is leading to your program being executed but nothing being created in DB.

Spring Boot Hibernate ManyToMany Relation using embedded model

I have a question about ManyToMany realation. Let's assume we have two model domains like Menu and RoleGroup,my Menu model includes a field named ' private RoleGroup roleGroup ' with #ManyToMany relation and #JoinTable with JoinColumns and InverseJoinColumns.
Imagine I already created an object like Menu that includes RoleGroup field with entityRepository .save in my database Here is my question, is there any way to update my object (considering to ManyToMany relation) without using native query? because when we use ManyToMany relationship hibernate handles it by creating third table like "Menu_RoleGroup" in database where as we don't have a domain like Menu_RoleGroup .
//Here is my application
package org.sayar.layout.domain;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Nationalized;
import org.sayar.layout.base.general.domain.GeneralDomain;
import org.sayar.layout.constants.SchemaList;
import org.sayar.layout.domain.uaa.Role;
import org.sayar.layout.domain.uaa.RoleGroup;
import org.springframework.data.annotation.Transient;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* This domain for store and transfer Menu
*
* #author Ehsan
*/
#Setter
#Getter
#AllArgsConstructor
#NoArgsConstructor
#JsonInclude(JsonInclude.Include.NON_NULL)
#Entity(name = Menu.TABLE_NAME)
#Table(name = Menu.TABLE_NAME, schema = SchemaList.LAYOUT)
public class Menu extends GeneralDomain {
#Transient
public final static String TABLE_NAME = "Menu";
public class CN {
public final static String title = "title";
public final static String description = "description";
public final static String banner = "banner";
}
#Nationalized
#Column(name = CN.title, length = 128, nullable = false)
private String title;
#Nationalized
#Column(name = CN.description, length = 1000)
private String description;
#Nationalized
#Column(name = CN.banner, length = 128)
private String banner;
/* Relationships */
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "Menu_RoleGroup",
schema = SchemaList.LAYOUT,
joinColumns = #JoinColumn(name = "menuId", referencedColumnName = GCN.id), //
inverseJoinColumns = #JoinColumn(name = "roleGroupId", referencedColumnName = GCN.id))
private Set<RoleGroup> roleGroupSet;
#OneToMany(mappedBy = MenuItem.CN.menu, fetch = FetchType.EAGER)
#JsonManagedReference
private Set<MenuItem> menuItemSet = new HashSet<>();
/* Constructors */
public Menu(String title, String banner, String description) {
this.title = title;
this.banner = banner;
this.description = description;
}
public Menu(String title, String banner, String description, Set<RoleGroup> roleGroupSet) {
this.title = title;
this.banner = banner;
this.description = description;
this.roleGroupSet = roleGroupSet;
}
public Menu(String id) {
super(id);
}
/* Other classes or enumerations */
}
.
.
.
.
.
package org.sayar.layout.domain.uaa;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Table;
import org.hibernate.annotations.Nationalized;
import org.sayar.layout.base.general.domain.GeneralDomain;
import org.sayar.layout.constants.SchemaList;
import org.springframework.data.annotation.Transient;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* This domain for store and transfer RoleGroup
*
* #author Ehsan
*
*/
#Setter
#Getter
#AllArgsConstructor
#NoArgsConstructor
#JsonInclude(JsonInclude.Include.NON_NULL)
#Entity(name = RoleGroup.TABLE_NAME)
#Table(name = RoleGroup.TABLE_NAME, schema = SchemaList.UAA)
public class RoleGroup extends GeneralDomain {
#Transient
public final static String TABLE_NAME = "RoleGroup";
public class CN {
public final static String title = "title";
public final static String status = "status";
}
#Nationalized
#Column(name = CN.title, length = 128, nullable = false)
private String title;
#Enumerated(EnumType.STRING)
#Column(name = CN.status, nullable = false)
private Status status;
public RoleGroup(String id) {
super(id);
}
/* Relationships */
/* Constructors */
/* Other classes or enumerations */
public enum Status {
ACTIVE, DE_ACTIVE
}
}
.
.
.
package org.sayar.layout.service.menu;
import org.sayar.layout.base.util.Print;
import org.sayar.layout.domain.Menu;
import org.sayar.layout.repository.megaitem.MegaItemRepository;
import org.sayar.layout.repository.menu.MenuRepository;
import org.sayar.layout.repository.menuitem.MenuItemRepository;
import org.sayar.layout.rest.menu.dto.*;
import org.springframework.stereotype.Service;
import org.sayar.layout.dao.menu.MenuDaoImpl;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Mono;
/**
* Spring service implementation for the Menu entity.
*
* #author Ehsan
*/
#Service
#RequiredArgsConstructor
public class MenuServiceImpl implements MenuService {
private final MenuDaoImpl entityDao;
private final MenuRepository entityRepository;
private final MenuItemRepository menuItemRepository;
private final MegaItemRepository megaItemRepository;
#Override
public Mono<ResponseEntity<Boolean>> create(ReqMenuCreateDTO entity, String userId) {
return Mono.just(entityRepository.save(entity.map(userId)))
.flatMap(createdEntity -> Mono.just(ResponseEntity.ok().body(true))
)
.defaultIfEmpty(ResponseEntity.ok().body(false));
}
#Transactional
#Override
public Mono<ResponseEntity<Boolean>> update(String id, ReqMenuUpdateDTO entity) {
Mono.just(entityRepository.update(id, entity.getTitle(), entity.getBanner(), entity.getDescription())).subscribe();
Mono.just(entityRepository.deleteRoleMenu(id)).subscribe();
Print.print("title", entity);
if (entity.getRoleGroupIdSet() != null && !entity.getRoleGroupIdSet().isEmpty())
for (String roleId : entity.getRoleGroupIdSet()) {
Mono.just(entityRepository.updateRoleMenu(id, roleId)).subscribe();
}
return Mono.just(ResponseEntity.ok().body(true));
}
.
.
.
.
.
package org.sayar.layout.repository.menu;
import org.sayar.layout.constants.SchemaList;
import org.sayar.layout.repository.menu.dto.ResRoleGetListRepoDTO;
import org.sayar.layout.rest.menu.dto.ResMenuGetListDTO;
import org.sayar.layout.repository.menu.dto.ResMenuGetOneRepoDTO;
import org.sayar.layout.rest.menu.dto.ResMenuGetOneDTO;
import org.sayar.layout.rest.menu.dto.ResMenuGetPageDTO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
import org.sayar.layout.domain.Menu;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
/**
* Spring Data SQL Server repository for the Menu entity.
*
* #author Ehsan
*/
#Repository
public interface MenuRepository extends JpaRepository<Menu, String> {
// UPDATE ALL STARTS HERE
#Transactional
#Modifying
#Query(value = "UPDATE Menu AS m SET m.title = :title , m.description = :description, m.banner = :banner WHERE m.id = :id")
Integer update(#Param("id") String id, #Param("title") String title, #Param("description") String description, #Param("banner") String banner);
#Transactional
#Modifying
#Query(value = "DELETE FROM layout.Menu_RoleGroup WHERE menuId = :id", nativeQuery = true)
Integer deleteRoleMenu(#Param("id") String id);
#Transactional
#Modifying
#Query(value = "INSERT INTO layout.Menu_RoleGroup (menuId,roleGroupId) VALUES (:menuId,:roleGroupId)", nativeQuery = true)
Integer updateRoleMenu(#Param("menuId") String menuId, #Param("roleGroupId") String roleGroupId);
}
Actually I find out how to solve it!
In this case I have to create a domain model like MenuRoleGroup as an Entity and then add an Embeddable field e.g MenuRoleGroupEmbeddable and use create #EmbeddedId field within MenuRoleGroup.
then add the primary key of Menu and RoleGroup within MenuRoleGroupEmbeddable.
so Spring Data is able to create MenuRoleGroupRepository that extends JPA Repository and but notice that this table has two primary keys not one.
notice that MenuRoleGroupEmbeddable field within MenuRoleGroup doesn't has relationship but Menu and RoleGroup both have #ManyToOne relation with MenuRoleGroupEmbeddable model.
here is the example.
package org.sayar.wms.domain.Menu;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;
import org.sayar.wms.base.general.domain.GeneralDomain;
import org.sayar.wms.constants.SchemaList;
import org.sayar.wms.domain.container.Container;
import org.sayar.wms.domain.product.ProductContainerEmbeddable;
import org.springframework.data.annotation.Transient;
import javax.persistence.*;
import java.util.Date;
#Setter
#Getter
#AllArgsConstructor
#NoArgsConstructor
#JsonInclude(JsonInclude.Include.NON_NULL)
#Entity(name = MenuRoleGroup.TABLE_NAME)
#Table(name = MenuRoleGroup.TABLE_NAME, schema = SchemaList.WMS)
public class MenuRoleGroup {
#Transient
public final static String TABLE_NAME = "MenuRoleGroup";
public class CN {
public final static String startDate = "startDate";
}
#EmbeddedId
private MenuRoleGroupEmbeddable menuRoleGroupEmbeddable;
#JoinColumn(name = CN.startDate, referencedColumnName = GeneralDomain.GCN.id)
private Date startDate;
}
package org.sayar.wms.domain.Menu;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.sayar.wms.base.general.domain.GeneralDomain;
import org.sayar.wms.domain.container.Container;
import javax.persistence.CascadeType;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import java.io.Serializable;
import java.util.Set;
/**
* This domain for store and transfer Warehouse
*
* #author masoud
*/
#Setter
#Getter
#AllArgsConstructor
#NoArgsConstructor
#JsonInclude(JsonInclude.Include.NON_NULL)
#Embeddable
public class ProductContainerEmbeddable implements Serializable {
public class CN {
public final static String menuId = "menuId";
public final static String roleGroupId = "roleGroupId";
}
/* Relationships */
#ManyToOne
#JoinColumn(name = CN.menu, referencedColumnName = "id")
private Menu menu;
#ManyToOne
#JoinColumn(name = CN.roleGroup, referencedColumnName ="id")
private RoleGroup roleGroup;
/* Constructors */
/* Other classes or enumerations */
}
menuId and roleGroupId are both primary keys of hte MenuRoleGroup entity.