Search code examples
javahibernatesql-server-2012many-to-manyjunction-table

Why the primary id of a link / junction table row changes on existing rows when new row is added to it?


I'm running a web project on WildFly8 and my database is SQL Server 2012.

I created a junction table service_service_package to associate Service and ServicePackage entities in a ManyToMany relationship, since services can belong to many service packages and service packages may have multiple different services associated with them.

The junction table has following columns: id, service_id and service_package_id. Here's the SQL script creating the said junction table:

CREATE TABLE service_service_package
(
  id BIGINT NOT NULL IDENTITY(1,1),
  service_id BIGINT NOT NULL,
  service_package_id BIGINT NOT NULL,
  PRIMARY KEY (id)
);

Here's the relevant part of Service Entity:

@Entity
@Table(name = "service")
public class Service {

@ManyToMany(targetEntity=ServicePackage.class, fetch=FetchType.LAZY)
    @JoinTable(name = "service_service_package",
        joinColumns =
        @JoinColumn(name = "service_id"),
        inverseJoinColumns =
        @JoinColumn(name = "service_package_id")
    )
    private List<ServicePackage> servicePackages;

    @Transient
    public void addServicePackage(ServicePackage sp) {
        if (!this.servicePackages.contains(sp)) {
            this.servicePackages.add(sp);
        }    
    }
...
}

Here's the relevant part of ServicePackage Entity:

@Entity
@Table(name = "service_package")

public class ServicePackage {

@ManyToMany(targetEntity=Service.class, mappedBy="servicePackages")
private List<Service> services = new ArrayList<>();

...
}

I have view for services. One part of the view is a list of ServicePackages associated to the service. When I add ServicePackages to the list and press a save button in that view, which persists the Service, all the newly added Services in that list will be associated with the ServicePackages on the list.

Here's the relevant code from the mentioned view:

        for (ServicePackage sp : spList.getTempSpList()) {
            service.addServicePackage(sp);
        }
        service = (Service) service.save();

The save method persists the service and creates an entry to the junction table.

Now, all this works otherwise perfectly, BUT each time a new ServicePackage is added to the list and the Service is saved the existing links in the junction table get an incremented id as well, even though the addServicePackage in the Service class only adds ServicePackages that were not already associated with the Service

For example: I add a ServicePackage(id 4) to a Service(id 6) in the way described above, and save the Service. Now the junction table gets following entry, for example:

id       service_id        service_package_id
-------------------------------------------------
1        6                 4

Now, for example, in the same view, I add another ServicePackage(id 11) to the list and save the Service after that as usual. Then the table looks like this:

id       service_id        service_package_id
-------------------------------------------------
2        6                 4
3        6                 11

So, the id of the first link in the junction table changed from 1 to 2. Even though the method only added the ServicePackage(id 11) to the list of ServicePackages associated to the Service, since it recognized that the first one already existed (I have tested this with Println.)

My question is, how can I prevent the id of the previous link in the junction table from incrementing when that link is not changed. It means a row is deleted and a new one is added. I want the id of the first row to remain as 1. Any ideas, thank you?


Solution

  • The reason why all the existing primary ids of all "link rows" in the service_service_package junction table linking to a certain Service got overwritten and incremented when a new ServicePackage was linked to (or removed from) that same Service was simply that, the collection servicePackages in the entity Service was a List.

    I changed that collection to be a HashSet and the problem is solved. The reason being that unlike ArrayList, HashSet doesn't accept duplicates so the existing links stay as they are, with their id unchanged.