How to save One-To-Many entitiy - java

I am not able to save the following entity. I would like to select Lab when I trying to save Server.
#Entity
#Getter
#Setter
public class Lab {
#Id
#GeneratedValue
#Column(name = "ID")
private Long id;
#NotNull
#Column(name = "LAB_NAME")
private String labName;
#NotNull
#Column(name = "LAB_PRIME")
private String labPrime;
#NotNull
#Column(name = "LAB_SERVICE_IP", nullable = false)
private String serviceIp;
#Column(name = "LAB_OWNER", nullable = false)
#Enumerated(EnumType.STRING)
private LabOwner labOwner;
#Column(name = "LAB_RELEASE")
#Enumerated(EnumType.STRING)
private LabRelease labRelease;
#JsonIgnore
#OneToMany(fetch = FetchType.EAGER)
private Set<Server> servers;
public Lab() {
}
public Lab(String labName, String labPrime, String serviceIp, LabOwner labOwner, LabRelease labRelease, Set<Server> servers) {
this.labName = labName;
this.labPrime = labPrime;
this.serviceIp = serviceIp;
this.labOwner = labOwner;
this.labRelease = labRelease;
this.servers = servers;
}
}
Repositories:
public interface LabRepository extends JpaRepository<Lab, Long> {
}
public interface ServerRepository extends JpaRepository<Server, Long> {
}
Server Entitiy;
#Entity
#Getter
#Setter
public class Server {
#Id
#GeneratedValue
#Column(name = "ID")
private Long id;
#NotNull
#Column(name = "LOGICAL_IP")
private String logicalIp;
#NotNull
#Column(name = "INSTANCE_TYPE")
private String instanceType;
#NotNull
#Column(name = "HOST_NAME", nullable = false)
private String hostName;
#NotNull
#Column(name = "HDWR_TYPE", nullable = false)
private String hardwareType;
#NotNull
#Column(name = "A2_TYPE", nullable = false)
private String a2Type;
#ManyToOne(fetch = FetchType.LAZY)
private Lab lab;
public Server() {
}
public Server(String logicalIp, String instanceType, String hostName, String hardwareType, String a2Type, Lab lab) {
this.logicalIp = logicalIp;
this.instanceType = instanceType;
this.hostName = hostName;
this.hardwareType = hardwareType;
this.a2Type = a2Type;
this.lab = lab;
}
}
Controller:
#RestController
#RequestMapping(value = "services/")
public class GenericController {
#Autowired
LabRepository labRepository;
#Autowired
LabRepository serverRepository;
#RequestMapping(value = "server", method = RequestMethod.POST)
public Server create(#RequestBody Server server) {
return serverRepository.saveAndFlush(server);
}
}
I cannot use serverRepository.saveAndFlush(server). It says that S is not within its bound, should extend Lab .
However, when I extend Lab entitiy, my tables were merged. I would like to 2 seperated tables.

In your controller you are using LabRepository instead of ServerRepository. It should be:
#RestController
#RequestMapping(value = "services/")
public class GenericController {
#Autowired
LabRepository labRepository;
#Autowired
ServerRepository serverRepository;
#RequestMapping(value = "server", method = RequestMethod.POST)
public Server create(#RequestBody Server server) {
return serverRepository.saveAndFlush(server);
}
}

Related

MapStruct Page to List conversion issues

I am new to Spring and MapStruct. I am having issues with conversion from Page to List. I used the MapStruct mapper in the service. I need to fetch all products from DB, then convert to ProductResponse using MapStruct mapper and then return PagedResponse object but the following error appears:
java.lang.ClassCastException: org.springframework.data.domain.PageImpl cannot be cast to java.util.List
at org.walana.GP.service.ProductService.getAll(ProductService.java:67) ~[classes/:na]
at org.walana.GP.controller.ProductController.getAll(ProductController.java:40)
ReplaceNumber
#Entity
#Table(name = "replace_numbers")
public class ReplaceNumber extends UserDateAudit
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Size(max = 20)
private String partNumber;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "product_id", nullable = false)
private Product product;
public ReplaceNumber() {}
public ReplaceNumber(String partNumber)
{
this.partNumber = partNumber;
}
}
ReplaceNumberResponse
public class ReplaceNumberResponse
{
private Long id;
private String partNumber;
}
Product
#Entity
#Table(name = "products", indexes = {#Index(name= "part_number_index", columnList = "part_number", unique = true)})
public class Product extends UserDateAudit
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Column(name = "part_number", nullable = false)
#Size(max = 20)
private String partNumber;
#NotBlank
#Size(max = 255)
private String description;
#OneToMany(
mappedBy = "product",
cascade = CascadeType.ALL,
fetch = FetchType.EAGER,
orphanRemoval = true
)
#Fetch(FetchMode.SELECT)
private List<ReplaceNumber> replaceNumbers = new ArrayList<>();
#ManyToOne
#JoinColumn(name = "product_manufacturer_id", referencedColumnName = "id")
private ProductManufacturer manufacturer;
#ManyToOne
#JoinColumn(name = "product_model_id", referencedColumnName = "id")
private ProductModel model;
#ManyToOne
#JoinColumn(name = "product_category_id", referencedColumnName = "id")
private ProductCategory category;
#Column(name = "cost", nullable = false)
#DecimalMin(message = "Cost should be greater than 1", value = "1")
private float cost;
#Column(name = "price", nullable = false)
#DecimalMin(message = "Price should be greater than 0", value = "0")
private float price;
}
ProductResponse
public class ProductResponse
{
private Long id;
private String partNumber;
private String description;
private List<ReplaceNumberResponse> replaceNumberResponses;
private ProductManufacturerResponse manufacturer;
private ProductModelResponse model;
private ProductCategoryResponse category;
private float cost;
private float price;
}
ProductMapper
#Mapper(componentModel = "spring")
public interface ProductMapper
{
ProductResponse toProductResponse(Product product);
List<ProductResponse> toProductResponses(List<Product> products);
Product toProduct(ProductResponse productResponse);
}
PagedResponse
public class PagedResponse<T>
{
private List<T> content;
private int page;
private int size;
private long totalElements;
private int totalPages;
private boolean last;
public PagedResponse() {
}
public PagedResponse(List<T> content, int page, int size, long totalElements, int totalPages, boolean last) {
this.content = content;
this.page = page;
this.size = size;
this.totalElements = totalElements;
this.totalPages = totalPages;
this.last = last;
}
}
ProductService
#Service
public class ProductService
{
#Autowired
ProductRepository productRepository;
#Autowired
ProductMapper productMapper;
public PagedResponse<ProductResponse> getAll(UserPrincipal currentUser, int page, int size)
{
Pageable pageable = PageRequest.of(page, size, Sort.Direction.DESC, "createdAt");
Page<Product> products = productRepository.findAll(pageable);
if (products.getNumberOfElements() == 0)
{
return new PagedResponse<>(Collections.emptyList(), products.getNumber(),
products.getSize(), products.getTotalElements(), products.getTotalPages(), products.isLast());
}
List<ProductResponse> productResponses = productMapper.toProductResponses((List<Product>) products);
return new PagedResponse<>(productResponses, products.getNumber(),
products.getSize(), products.getTotalElements(), products.getTotalPages(), products.isLast());
}
}
ProductController
#RestController
#RequestMapping("/api/products")
public class ProductController
{
#Autowired
private ProductService productService;
private static final Logger logger = LoggerFactory.getLogger(ProductController.class);
#GetMapping
public PagedResponse<ProductResponse> getAll(#CurrentUser UserPrincipal currentUser,
#RequestParam(value = "page", defaultValue = AppConstants.DEFAULT_PAGE_NUMBER) int page,
#RequestParam(value = "size", defaultValue = AppConstants.DEFAULT_PAGE_SIZE) int size)
{
return productService.getAll(currentUser, page, size);
}
}
Replace
productMapper.toProductResponses((List<Product>) products)
with
productMapper.toProductResponses(products.getContent())

Java ModelMapper -Failed to convert java.util.List to java.util.List

I am using the Java ModelMapper library to map DTOs to ORM #Entity objects. I have the following test set up:
public class MapperTest {
#Autowired
private ModelMapper mapper;
#Autowired
private TicketRepository ticketRepo;
#Test
public void testTicket() {
Ticket ticket = ticketRepo.findById(4).get();
TicketDTO dto = mapper.map(ticket, TicketDTO.class);
assertThat(dto.getEquipmenDescription()).isEqualTo(ticket.getEquipment().getDescription());
assertThat(dto.getEquipmentNotes()).isEqualTo(ticket.getEquipmentNotes());
assertThat(dto.getId()).isEqualTo(ticket.getId());
assertThat(dto.getNotes()).isEqualTo(ticket.getNotes());
assertThat(dto.getOracleID()).isEqualTo(ticket.getOracleID());
assertThat(dto.getPropertyID()).isEqualTo(ticket.getPropertyID());
assertThat(dto.getNotes().size()).isEqualTo(ticket.getNotes().size());
for (TicketNoteDTO note : dto.getNotes()) {
assertThat(note.getId()).isNotEqualTo(0);
assertThat(note.getIssueDate()).isNotNull();
assertThat(note.getUserUserName()).isNotEmpty();
}
}
}
This fails with the following error:
org.modelmapper.MappingException: ModelMapper mapping errors:
1) Converter org.modelmapper.internal.converter.CollectionConverter#501c6dba failed to convert java.util.List to java.util.List.
The following are my Entity and corresponding DTOs. Getters and setters are omitted for brevity.
Ticket
#Entity
#Table(name = "ticket")
public class Ticket {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "equipment_notes")
private String equipmentNotes;
#Column(name = "is_open")
private boolean isOpen;
#Column(name = "oracle_id")
private String oracleID;
#ManyToOne
#JoinColumn(name = "equipment_id")
private EquipmentCategory equipment;
#Column(name = "property_id")
private String propertyID;
#OneToMany(mappedBy = "ticket")
private List<TicketNote> notes = new ArrayList<>();
}
TicketNote (getters and Setters omitted for brevity)
#Entity
#Table(name = "ticket_note")
public class TicketNote {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#ManyToOne
#JoinColumn(name = "ticket_id")
private Ticket ticket;
#ManyToOne
#JoinColumn(name = "user_id")
private AppUser user;
#Column(name = "issue_date")
private LocalDate issueDate;
#Column(name = "oracle_contact")
private String oracleContact;
#Column(name = "issue_resolved")
private boolean issueResolved;
}
TicketDTO
public class TicketDTO {
private int id;
private String equipmentNotes;
private boolean isOpen;
private String oracleID;
private String equipmenDescription;
private String propertyID;
private List<TicketNoteDTO> notes = new ArrayList<>();
}
TicketNoteDTO
public class TicketNoteDTO {
private int id;
private String userUserName;
private LocalDate issueDate;
private String oracleContact;
private boolean issueResolved;
}
I have some experience with the ModelMapper library, but I am not sure what the issue is. Any advice is appreciated.
Thanks.

How can I realize a ManyToOne relation using the CrudRepository (Spring Data and thymeleaf )?

I am using Spring boot and spring Data (CrudRepository) to persist entity passing by a form, but i have a ManyToOne relation between Product and StatutProduit (idStatutProduit as a foreign key in Produit entity), the problem that i dont know how to say to the controller that i have an object that depend to an other object...otherwise i have to create w form with thymeleaf for product class for sure with combo box to load statusProduct.
Produit Class (:
public class Produits implements Serializable {
private static final long serialVersionUID = 1L;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Id
#Basic(optional = false)
#NotNull
#Column(name = "ID_PRODUIT")
private BigDecimal idProduit;
#Column(name = "ID_OPERATEUR")
private BigInteger idOperateur;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "CODE")
private String code;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "LIBELLE")
private String libelle;
#Column(name = "POIDS")
private BigInteger poids;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 5)
#Column(name = "INDICE")
private String indice;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 10)
#Column(name = "CREE_PAR")
private String creePar;
#Column(name = "DATE_CREATION")
#Temporal(TemporalType.TIMESTAMP)
private Date dateCreation;
#Size(max = 10)
#Column(name = "MAJ_PAR")
private String majPar;
#Column(name = "DATE_MAJ")
#Temporal(TemporalType.TIMESTAMP)
private Date dateMaj;
#JoinColumn(name = "ID_STATUT_PRODUIT", referencedColumnName = "ID_STATUT_PRODUIT")
#ManyToOne(optional = false)
private StatutProduits idStatutProduit;
public Produits(BigDecimal idProduit, String code, String libelle,
String indice, String creePar) {
this.idProduit = idProduit;
this.code = code;
this.libelle = libelle;
this.indice = indice;
this.creePar = creePar;
}
StatusProduct class:
public class StatutProduits implements Serializable {
private static final long serialVersionUID = 1L;
fields consider using these annotations to enforce field validation
#Id
#Basic(optional = false)
#NotNull
#Column(name = "ID_STATUT_PRODUIT")
private BigDecimal idStatutProduit;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "CODE")
private String code;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 45)
#Column(name = "LIBELLE")
private String libelle;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 10)
#Column(name = "CREE_PAR")
private String creePar;
#DateTimeFormat(pattern = "yyyy-MM-dd")
#Column(name = "DATE_CREATION")
#Temporal(TemporalType.TIMESTAMP)
private Date dateCreation;
#Size(max = 10)
#Column(name = "MAJ_PAR")
private String majPar;
#DateTimeFormat(pattern = "yyyy-MM-dd")
#Column(name = "DATE_MAJ")
#Temporal(TemporalType.TIMESTAMP)
private Date dateMaj;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "idStatutProduit")
private List<Produits> produitsList;
public StatutProduits() {
}
public StatutProduits(BigDecimal idStatutProduit) {
this.idStatutProduit = idStatutProduit;
}
public StatutProduits(BigDecimal idStatutProduit, String code, String libelle, String creePar) {
this.idStatutProduit = idStatutProduit;
this.code = code;
this.libelle = libelle;
this.creePar = creePar;
}
public BigDecimal getIdStatutProduit() {
return idStatutProduit;
}
public void setIdStatutProduit(BigDecimal idStatutProduit) {
this.idStatutProduit = idStatutProduit;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getLibelle() {
return libelle;
}
public void setLibelle(String libelle) {
this.libelle = libelle;
}
public String getCreePar() {
return creePar;
}
public void setCreePar(String creePar) {
this.creePar = creePar;
}
public Date getDateCreation() {
return dateCreation;
}
public void setDateCreation(Date dateCreation) {
this.dateCreation = dateCreation;
}
public String getMajPar() {
return majPar;
}
public void setMajPar(String majPar) {
this.majPar = majPar;
}
public Date getDateMaj() {
return dateMaj;
}
public void setDateMaj(Date dateMaj) {
this.dateMaj = dateMaj;
}
public List<Produits> getProduitsList() {
return produitsList;
}
public void setProduitsList(List<Produits> produitsList) {
this.produitsList = produitsList;
}
ProduitService class :
#Service
public class ProduitService {
#Autowired
private ProduitRepository produitrepository ;
public void addProduit(Produits p ) {
}
}
Take a look at this page https://spring.io/guides/gs/accessing-data-rest/. Here you can see this piece of code:
package hello;
import java.util.List;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
If you make the repository this way Spring will create the controller and the service to fit your #Entity.

Can't get list of nested objects in JSON

i have faced with the problem, that JSON doesn't containe the list of nested objects.
I have 2 classes, one of them is carrying information about auto service, another one containes information about services.
One autoservice can has many services. So, we have the relation - one to many .
AutoService class:
#Entity
#Table(name = "AutoRate")
public class AutoService {
public AutoService() {
}
#Id
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "increment")
private long id;
#Column(name = "serviceName", nullable = false)
private String serviceName;
#Column(name = "imageURL", nullable = false)
private String imageURL;
#Column(name = "mapCoordinate", nullable = false)
private String mapCoordinate;
#Column(name = "websiteURL", nullable = false)
private String websiteURL;
#Column(name = "phoneNumber", nullable = false)
private String phoneNumber;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "autoServiceId")
private List<Service> services;
public long getId() {
return id;
}
public String getServiceName() {
return serviceName;
}
public String getImageURL() {
return imageURL;
}
public String getMapCoordinate() {
return mapCoordinate;
}
public String getWebsiteURL() {
return websiteURL;
}
public String getPhoneNumber() {
return phoneNumber;
}
}
Service class:
#Entity
#Table(name = "Service")
public class Service {
public Service() {
}
#Id
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "increment")
#Column(name = "serviceId", unique = true, nullable = false)
private long serviceId;
#Column(name = "serviceName", nullable = false)
private String serviceName;
#Column(name = "category", nullable = false)
private String category;
#Column(name = "price", nullable = false)
private int price;
#Column(name = "autoServiceId", nullable = false)
private long autoServiceId;
public long getId() {
return serviceId;
}
public String getCategory() {
return category;
}
public int getPrice() {
return price;
}
public String getServiceName() {
return serviceName;
}
public long getAutoServiceId() {
return autoServiceId;
}
}
Also i am using the JpaRepository to get objects from db:
public interface AutoRateRepository extends JpaRepository<AutoService, Long> {
}
Here is Controller class:
#RestController
#RequestMapping("/directory")
public class ServiceController {
#Autowired
private AutoRateService dataBaseService;
#RequestMapping(value = "/get", method = RequestMethod.GET)
#ResponseBody
public List<AutoService> getData(){
List<AutoService> dataList = dataBaseService.getAll();
return dataList;
}
}
But then when i am trying to get JSON object i am getting next:
[
{
"id": 1,
"serviceName": "SpeedyName",
"imageURL": "Url for speedy",
"mapCoordinate": "123123 44121 ",
"websiteURL": "speedy.com",
"phoneNumber": "1231251"
},
{
"id": 2,
"serviceName": "Другой сервис",
"imageURL": "Урл для второго сервиса",
"mapCoordinate": "123 12фывфы",
"websiteURL": "другойсервис.ком",
"phoneNumber": "12312333"
}
]
There is not lists of nested objects from database ( List<Services>
Can you help me to resolve this problem ?
I was told that i had missed the #JsonManagedReference annotation, but it didn't helped me (
As specified in the comments, you're missing a getServices() method in the AutoService entity exposing the collection for serialization.
As a side note, be weary if your Service entity has a back reference to the parent AutoService. If it does, you'll need to make sure your JSON framework knows how to handle cyclic loops or you will need to trigger ignoring the back reference when you serialize the AutoService instances to avoid a stack overflow.

Embeddable/ ManyToOne/ OneToMany not working

I' m quite knew to Java and currently I am working on a ChatProgramm.
So I want to create a table Messages embedded with the ID (USERNUMBER) of my table Contacts using Injections.
Here' s the class of my Message:
#Embeddable
#Entity(name = "MESSAGE")
public class Message implements Serializable {
#ManyToOne
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "INCOME_MESSANGE", nullable = false)
private String incomingMessage;
#EmbeddedId
#JoinColumn(name = "USERNUMBER", nullable = false)
private Contact contact;
ChatApplicationRemote chatApplicationRemote;
public Message(String ip, String msg) throws IOException {
incomingMessage = msg;
contact = chatApplicationRemote.getcontactByIP(ip.toString());
}
public Message(){
}
public String getIncomingMessage() {
return incomingMessage;
}
public Contact getContact() {
return contact;
}
And here my contacts:
#Entity(name = "CONTACTS")
#Embeddable
public class Contact implements Serializable {
/**
*
*/
private static final long serialVersionUID = -6855140755056337926L;
#Column(name = "NAME", nullable = false)
private String name;
#Column(name = "PRENAME", nullable = false)
private String vorname;
#Column(name = "IP", nullable = false)
private String ip;
#Column(name = "PORT", nullable = false)
private Integer port;
#Id
#OneToMany(mappedBy = "Message.incomingMessage")
#Column(name = "USERNUMBER", nullable = false)
private String usernumber;
public Contact(String usernumber, String name, String vorname, String ip, String port) {
super();
this.usernumber = usernumber;
this.name = name;
this.vorname = vorname;
this.ip = ip;
this.port = Integer.parseInt(port);
}
public Contact(){
}
public String getUsernumber() {
return usernumber;
}
//......
So in my Message, I get two errors:
#ManyToOne throws : Target entity "java.lang.String" is not an Entity
#EmbeddedID throws : de.nts.data.Contact is not mapped as an embeddable
So I googled for a while.. and found something abouta orm.xml which I hadn't have. And even if I create one, #EmbeddedID throws:Embedded ID class should include method definitions for equals() and hashcode() and the orm.xml Attribute "usernumber" has invalid mapping type in this context.
Can anyone please help?
Try
#Entity
public class Message implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name = "INCOME_MESSANGE", nullable = false)
private String incomingMessage;
#ManyToOne
#JoinColumn(name = "USERNUMBER", nullable = false)
private Contact contact;
#Transient
ChatApplicationRemote chatApplicationRemote;
..
}
#Entity
public class Contact implements Serializable {
private static final long serialVersionUID = -6855140755056337926L;
#Column(name = "NAME", nullable = false)
private String name;
#Column(name = "PRENAME", nullable = false)
private String vorname;
#Column(name = "IP", nullable = false)
private String ip;
#Column(name = "PORT", nullable = false)
private Integer port;
#Id
#Column(name = "USERNUMBER", nullable = false)
private String usernumber;
#OneToMany(mappedBy = "incomingMessage")
private LIst<Message> messages;
..
}
maybe as a starting point, but as JB Nizet suggested, start with some simple JPA/Java demos to get the basics first and build up. Your example has many more errors then just what the exception was showing, none of which are solved by just throwing in an ORM.xml.

Categories