I use OneToOne
in the spring data JPA
and I want to delete a record from the Address
table without touching the user. But I can't.
If I remove User
, in this case Address
is removed, that's good.
But how can you delete an Address
without touching the User
?
https://github.com/myTestPercon/TestCascade
User.Java
@Entity
@Table(name = "user", schema = "testCascade")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name")
private String name;
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private Address address;
// Getter and Setter ...
}
Address.java
@Entity
@Table(name = "address", schema = "testCascade")
public class Address implements Serializable {
@Id
private Long id;
@Column(name = "city")
private String city;
@OneToOne
@MapsId
@JoinColumn(name = "id")
private User user;
// Getter and Setter ...
}
DeleteController.java
@Controller
public class DeleteController {
@Autowired
ServiceJpa serviceJpa;
@GetMapping(value = "/deleteAddressById")
public String deleteAddressById () {
serviceJpa.deleteAddressById(4L);
return "redirect:/home";
}
}
In order to solve this problem, you need to read the hibernate Documentation Hibernate Example 162
, Example 163
, Example 164
.
And also I recommend to look at this is Using @PrimaryKeyJoinColumn annotation in spring data jpa
This helped me in solving this problem.
And also you need to specify the parameter orphanRemoval = true
User.java
@Entity(name = "User")
@Table(name = "user", schema = "testother")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name")
private String name;
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private Address address;
public void addAddress(Address address) {
address.setUser( this );
this.address = address;
}
public void removeAddress() {
if ( address != null ) {
address.setUser( null );
this.address = null;
}
}
// Getter and Setter
}
Address.java
@Entity(name = "Address")
@Table(name = "address", schema = "testother")
public class Address implements Serializable {
@Id
private Long id;
@Column(name = "city")
private String city;
@OneToOne
@MapsId
@JoinColumn(name = "id")
private User user;
// Getter and Setter
}
DeleteController .java
@Controller
public class DeleteController {
@Autowired
ServiceJpa serviceJpa;
@GetMapping(value = "/deleteUser")
public String deleteUser () {
User user = serviceJpa.findUserById(2L).get();
user.removeAddress();
serviceJpa.saveUser(user);
return "/deleteUser";
}
}
Or make a custom SQL query.
@Repository
public interface DeleteAddress extends JpaRepository<Address, Long> {
@Modifying
@Query("delete from Address b where b.id=:id")
void deleteBooks(@Param("id") Long id);
}