Home > other >  How to retrieve a record without using embeddedID?
How to retrieve a record without using embeddedID?

Time:12-31

So I have the following entity:

@Entity
@Table(name = "appointment")
public class Appointment {
@EmbeddedId 
private AppointmentId id = new AppointmentId();

@ManyToOne(fetch = FetchType.LAZY)
@MapsId("customerId")
@JoinColumn(name = "customerId") //Remember to use joincolumns to rename the generated column is spring creates it
private Customer customer;

@ManyToOne(fetch = FetchType.LAZY)
@MapsId("barberId")
@JoinColumn(name = "barberId") //Remember to use joincolumns to rename the generated column is spring creates it
private Barber barber;

@Column(name = "notes")
private String notes;

public Appointment(Customer customer, Barber barber, String notes) {
    this.customer = customer;
    this.notes = notes;
    this.barber = barber;
}

public Appointment() {
}

@JsonBackReference
public Customer getCustomer() {
    return customer;
}

public void setCustomer(Customer customer) {
    this.customer = customer;
}

public String getNotes() {
    return notes;
}

public void setNotes(String notes) {
    this.notes = notes;
}

@Override
public String toString() {
    return "Appointment{"  
            ", notes='"   notes   '\''  
            '}';
}
}

And this is the AppointmentId:

@SuppressWarnings("serial")
@Embeddable
public class AppointmentId implements Serializable {
    private Integer barberId;
    private Integer customerId;
}

Now I was following a tutorial in which I managed to accomplish what I wanted to do. The key was to add the @EmbeddedId annotation and create the AppointmentId class.

I currently have 3 records in my 'Appointment' table in the DB. And each record has a primary key and the value is 1,2,3 resepctively.

I'm trying to fetch the 2nd record so I'm using the .findById(2) method from my interface which extends JpaRespository<Appointment, Integer> but I get the following error. I'm not sure why:


org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.gogobarber.barber.entities.Appointment. Expected: class com.gogobarber.barber.entities.AppointmentId, got class java.lang.Integer

I mean the error is self explantory.. it's asking for the ID in the form of AppointmentId but how can I create such an object without knowing the customer or the barber id?

EDIT = This is my table schema for Appointments:

Table: appointment
Columns:
idappointment int AI PK 
notes varchar(255) 
barberId int 
customerId int

EDIT =

Controller:

@DeleteMapping("/appointment/{appointmentId}")
public void deleteAppointment(@PathVariable String appointmentId)
{
    appointmentService.deleteAppointment(appointmentId);
}

Service:

@Transactional
public void deleteAppointment(String appointmentId) {
    appointmentRepo.deleteById(Integer.valueOf(appointmentId));
}

CodePudding user response:

I had similar problem recently. At first to get the composite primary key I used the @EmbeddedId but later I found out that adding additional abstraction level added more complexity and for example using of HashMap or HashSet needs additional logic to represent the keys. So my recommendation is to use the internal generated database ID as key and for unique columns just add a unique constrain:

@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "barberId", "customerId" }) })

CodePudding user response:

I'm trying to fetch the 2nd record so I'm using the .findById(2) method from my interface which extends JpaRespository<Appointment, Integer> but I get the following error. I'm not sure why

public class Appointment {
@EmbeddedId 
private AppointmentId id = new AppointmentId();

It is wrong that you have declared your entity Id as of type AppointmentId and then later in your JPA repository you declare that you have an id of Integer

Start by correcting your repository layer schema as

JpaRespository<Appointment, AppointmentId>

Also if you make those corrections you can declare methods in your repository that could search only from one of those properties of the id.

You can declare in your repository custom methods which will be implemented by spring data if they have the correct name that spring data can understand. You can use the following

List<Appointment> findByIdCustomerId(Integer customerId); <-- will retrieve results only by customerId
List<Appointment> findByIdBarberId(Integer barberId); <-- will retrieve results only by barberId

It's asking for the ID in the form of AppointmentId but how can I create such an object without knowing the customer or the barber id?

As I see it structured the appointment is the relation (intermediate table) that connects a barber with a customer. So to create an appointment you have to know between which barber and which customer it will be. So this could explain how you can create such an object, as by knowing the customer you know the customerId and by knowing the barber you know the barberId.

Here I can see a loophole in your design though. Should a specific barber with a specific customer have only 1 appointment in Database? Or could they have multiple future and past appointments. If this is the case then the Id you have declared in Appointment class is not enough.

  • Related