spring 数据 jpa 中的 OneToOne CascadeType

OneToOne CascadeType in spring data jpa

我在 spring data JPA 中使用 OneToOne 并且我想从 Address table 不接触用户。但是我不能。

如果我去掉User,在这种情况下Address就去掉了,这样就好了。

但是如何在不触及 User 的情况下删除 Address

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


        }

    }
 public class Address {

   @Id
    private Long id;      

    @MapsId
    @JoinColumn(name = "id")
    private User user;
  }

@JoinColumn(name = "id") 重命名为 @JoinColumn(name = "user_id")

你不能说指向用户的列就是地址的 ID

你的映射有误,这就是问题所在。

试试下面的方法看看

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(cascade=CascadeType.ALL)
    @JoinColumn(name="foriegn key column in user table for address example.. address_id")
    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;

    //name of the address variable in your user class
    @OneToOne(mappedBy="address", 
        cascade={CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
                    CascadeType.REFRESH})
    private User user;


    // Getter and Setter ...


}

为了解决这个问题,需要阅读hibernate Documentation Hibernate Example 162, Example 163, Example 164.

我还建议看看这个

这帮助我解决了这个问题。

而且你还需要指定参数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
    }

删除控制器。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";
        }

    }

或自定义 SQL 查询。

    @Repository
    public interface DeleteAddress extends JpaRepository<Address, Long> {

        @Modifying
        @Query("delete from Address b where b.id=:id")
        void deleteBooks(@Param("id") Long id);

    }