Search code examples
springhibernatespring-data-jpaspring-datahibernate-mapping

OneToOne CascadeType in spring data jpa


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";


        }

    }

Solution

  • 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);
    
        }