1

i have a contract class with 3 primary keys, the id is auto_inctement, the convention and the organization are foreign primary keys

@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
}

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

this is the result when i add a new convention

{
  "id": 50,
  "shortname": "string",
  "fullname": "string"
}

this is the result when i add a new convention:

{
  "id": 100,
  "name": "string"
}

Json for add a new contract:

{
  "conventionId": 50,
  "organizationId": 100
}

in this step it shows me this error:

detached entity passed to persist: com.back.domain.Convention; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.back.domain.Convention

for mapping i used mapstruct, below is the contract mapping class

@Mapper(uses = { ConventionMapper.class, OrganizationMapper.class })
public interface ContractMapper extends EntityMapper<ContractDTO, Contract> {

    @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;
    }

}

this is the method to add a new contract in the service:

@Override
public ContractDTO save(ContractDTO contractDTO) {
    Contract contract = ContractMapper.toEntity(contractDTO);
    contract = ContractRepository.save(contract);
    return ContractMapper.toDto(contract);
}

here is the link to the project in github

Aymen Kanzari
  • 1,225
  • 3
  • 22
  • 41
  • Well, fix the code which calls persist() with a detached entity as argument. Why in hell are convention and organization part of the ID? – JB Nizet Apr 14 '18 at 08:21
  • sorry @JBNizet i modified my question because i think the problem is in the mapping, when i don't use mapstruct, adding a new contract works without a problem – Aymen Kanzari Apr 14 '18 at 18:06
  • Did you try the 'adder' method in MapStruct? If you add a child entity, it needs to contain a back reference to its parent. MapStruct has a mechanism. Checkout: http://mapstruct.org/documentation/stable/reference/html/#mapping-collections – Sjaak Apr 30 '18 at 22:32
  • More information about that error: https://stackoverflow.com/questions/27672337/detached-entity-passed-to-persist-error/ – Ilya Ovesnov May 01 '18 at 20:55

0 Answers0