简体   繁体   中英

Hibernate: saving an entity with foreign primary key

I have a database with two entities ( Product and Feedback ). Feedback has a single foreign key that refers to Product, whose primary key is an integer. They are therefore in a one-to-one relationship .

I want to add a new Feedback entry to the database with my web application. To do so I'm trying to perform a PUT request to my Spring server from my Angular client application.

The client has an Object of class Feedback with the following attributes (content of Feedback.ts )

export class Feedback {
  constructor(
    public productId: number,
    public score: number,
    public preferred: boolean,
    public textNote: string
  ) {
  }
}

The class Feedback.java , server side:

@Entity
@Table(name = "feedback")
public class Feedback implements Serializable {
    @Id
    @JoinColumn(name = "product", unique = true)
    @OneToOne(cascade = CascadeType.ALL)
    private Product product;

    @Column(name = "score")
    private double score;

    @Column(name = "preferred")
    private boolean preferred;

    @Column(name = "textnote")
    private String textNote;

    // ... getters, setters, constructor

}

As you can see there is a non-matching attribute: productId is a number , while product is of class Product . How can I give the Spring application the correct object in order to save it in the database?

I'm trying to follow the Hibernate guidelines and as far as I understood it would be a bad practice to use an attribute in the java class of type int instead of Product . What should I do?

You create a new Product with the productId from the FE. Now you can create a new Feedback object with all types set. This you can then store in the database.

[Edit]

Usually, you have data transfer object (DTO)in the backend. Those will as the name suggests transport data do nothing else. Endpoints in the backend will always get DTOs which are the same as in the FE. In your case create a FeedbackDto.

public class FeedbackDto {
   Long productId;
   Double score;
   Boolean preferred;
   String textNote;
}

The Endpoint will receive this Object which has the same fields as the Feedback from the FE. Spring will create and fill you the object from the values in the JSON body of the request

From the FeedbackDto you create now a Feedback entity:

new Feedback(new Product(feedbackDto.productId), feedbackDto.score, feedbackDto.preferred, feedbackDto.textNote)

Now you can save this Feedback entity into your database.

I had a similar issue as you had, and this blog post helped me solve it: https://www.baeldung.com/spring-data-rest-relationships . This works very well if you are also using the Spring Data REST, but I think you can adapt it to your usage.

Basically, after you create your Feedback entry (with an initial POST request), you should perform another PUT request to associate the Feedback entry to your Product . For your example, you could have something like:

curl -i -X PUT 
 -d "http://localhost:8080/feedback/1" 
 -H "Content-Type:text/uri-list" http://localhost:8080/product/1/feedbackProduct

You can extend a DefaultConversionService and implement a custom converter to convert id to product

 @Configuration
 public static class Config {
   @Bean
   public ConversionService conversionService () {
      DefaultConversionService service = new DefaultConversionService();
      service.addConverter(new IdToProductConverter());
      return service;
   }
 }

Then the IdToProductConverter will receive the id and can lookup the product from the DB

class IdToProductConverter implements Converter<String, Product> {
    @Override
    public Product convert(String source) {
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM