O repositório Spring também salva objetos que não estou tentando salvar

O problema é que um dia descobrimos que, se estamos salvando um objeto no repositório de inicialização do Spring, outros objetos que são alterados no mesmo método também são atualizados e mantidos no banco de dados.

A curiosidade é enorme para descobrir por que isso realmente acontece. Eu criei um projeto de amostra usandoSpring Initializr e algum código de modelo para mostrar a situação real (tentou manter o número de dependências o mais baixo possível).

O uso do Spring boot versão 1.5.11 (SNAPSHOT) e o projeto têm as seguintes dependências:

dependencies {
  compile('org.springframework.boot:spring-boot-starter-data-jpa')
  compile('org.springframework.boot:spring-boot-starter-web')
  compile('org.mariadb.jdbc:mariadb-java-client:2.1.0')
  testCompile('org.springframework.boot:spring-boot-starter-test')
}

Agora ao ponto:

O projeto possui duas entidades,Pet:

@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Pet.class)
public class Pet {
  @Id
  @GeneratedValue
  private long id;
  private String type;

  public Pet() {}
  public String getType() { return type; }
  public void setType(String type) { this.type = type; }
}

eUser:

@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = User.class)
public class User {
  @Id
  @GeneratedValue
  private long id;
  private String name;

  public User() {}
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
}

Ambas as entidades também possuem repositórios,Pet:

@Repository
public interface PetRepository extends CrudRepository<Pet, Long> {
  Pet findPetById(Long id);
}

User:

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
  User findUserById(Long id);
}

E um serviço simples, onde a mágica realmente acontece (eu pré-salvei umPet e umUser objeto, com nome e tipo diferentes)

@Service
public class UserService {
  @Autowired
  UserRepository userRepository;
  @Autowired
  PetRepository petRepository;

  public User changeUserAndPet() {
    User user = userRepository.findUserById(1L);
    Pet pet = petRepository.findPetById(1L);

    user.setName("Kevin");
    pet.setType("Cow");
    userRepository.save(user);
    return user;
  }

}

Logo após ligaruserRepository.save(user); o objeto Pet também é atualizado no banco de dados com o novo tipo de 'Cow'. Por que exatamente isso acontece se eu apenas salvei o arquivoUser objeto? Isso pretende ser assim?

Há também um controlador simples e um ponto de extremidade de teste simples para chamar o método de serviço que provavelmente não é importante para a questão, mas ainda o adicionarei aqui por uma questão de integridade.

@RestController
public class UserController {

  @Autowired
  UserService userService;

  @RequestMapping(value = "/test", method = RequestMethod.GET)
  public User changeUserAndPet() {
    return userService.changeUserAndPet();
  }

}

Quaisquer explicações / dicas são apreciadas e fique à vontade para solicitar informações / códigos extras no github.

questionAnswers(2)

yourAnswerToTheQuestion