title: composite key with mapstruct - detached entity passed to persist
body: <p>i have a contract class with 3 primary keys, the id is auto_inctement, the convention and the organization are foreign primary keys</p>
  
  <pre><code>@Entity
  @IdClass(ContractIdentity.class)
  @Table(name = "contract")
  public class contract implements Serializable {
  
    private static final long serialVersionUID = 1L;
  
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    private Long id;
  
    @Id
    @ManyToOne
    private Convention convention;
  
    @Id
    @ManyToOne
    private Organization organization;
  
    //getter and setter
  }
  
  public class ContractIdentity implements Serializable {
  
    private static final long serialVersionUID = 1L;
  
    private Long id;
  
    private Long convention;
  
    private Long organization;
  
    //getter and setter
    //hashCode and equals
  }
  </code></pre>
  
  <p>first i add a new convention, then i add a new organization, then when i add a new contract i just enter the convention's id and the organization's id</p>
  
  <p>this is the result when i add a new convention</p>
  
  <pre><code>{
    "id": 50,
    "shortname": "string",
    "fullname": "string"
  }
  </code></pre>
  
  <p>this is the result when i add a new convention:</p>
  
  <pre><code>{
    "id": 100,
    "name": "string"
  }
  </code></pre>
  
  <p>Json for add a new contract:</p>
  
  <pre><code>{
    "conventionId": 50,
    "organizationId": 100
  }
  </code></pre>
  
  <p>in this step it shows me this error:</p>
  
  <blockquote>
    <p>detached entity passed to persist: com.back.domain.Convention; nested
    exception is org.hibernate.PersistentObjectException: detached entity
    passed to persist: com.back.domain.Convention</p>
  </blockquote>
  
  <p>for mapping i used mapstruct, below is the contract mapping class</p>
  
  <pre><code>@Mapper(uses = { ConventionMapper.class, OrganizationMapper.class })
  public interface ContractMapper extends EntityMapper&lt;ContractDTO, Contract&gt; {
  
      @Override
      @Mapping(source = "convention.id", target = "conventionId")
      @Mapping(source = "organization.id", target = "organizationId")
      ContractDTO toDto(Contract contract);
  
      @Override
      @Mapping(source = "conventionId", target = "convention")
      @Mapping(source = "organizationId", target = "organization")
      Contract toEntity(ContractDTO contractDTO);
  
      default Contract fromId(Long id) {
          if (id == null) {
              return null;
          }
          Contract contract = new Contract();
          contract.setId(id);
          return contract;
      }
  
  }
  </code></pre>
  
  <p>this is the method to add a new contract in the service:</p>
  
  <pre><code>@Override
  public ContractDTO save(ContractDTO contractDTO) {
      Contract contract = ContractMapper.toEntity(contractDTO);
      contract = ContractRepository.save(contract);
      return ContractMapper.toDto(contract);
  }
  </code></pre>
  
  <p>here is the link to the project in <a href="https://github.com/akanzari/convention" rel="nofollow noreferrer">github</a></p>