【问题标题】:Spring boot JPA One to One MappingSpring Boot JPA 一对一映射
【发布时间】:2020-08-18 22:51:41
【问题描述】:

我有两个实体如下:

用户实体

@Entity
@Table(name = "user")
@Getter
@Setter
@NoArgsConstructor
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "id")
    private UserDetails userDetails;

    @Column(name = "description")
    private String description;

    public User(final String description) {
        this.description = description;
    }
}

UserDetails 实体

@Entity
@Table(name = "user_details")
@Getter
@Setter
@NoArgsConstructor
public class UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "description")
    private String description;

    @OneToOne(mappedBy = "userDetails")
    private User user;

    public UserDetails(final String description) {
        this.description = description;
    }
}

我的flyway脚本如下:

CREATE TABLE `user` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`description` varchar(255)
);

CREATE TABLE `user_details` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`user_id` int,
`description` varchar(255)
);

ALTER TABLE `user_details` ADD FOREIGN KEY (`user_id`) REFERENCES `user` (`id`);

当我启动应用程序时,表格创建得很好。我希望 user 表是父表,而 user_details 表是子表,它被创建得非常好。但是当我在数据库中插入一个用户时,user_details 表中的 user_id 列被存储为空。下面是我的控制器。

用户控制器

@RestController
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users/{id}")
    public ResponseEntity < User > getUser(@PathVariable("id") Long id) {

        User user = userRepository.getOne(id);
        return new ResponseEntity < > (user, HttpStatus.OK);
    }

    @PostMapping("/users")
    public ResponseEntity < User > saveUser(@Valid @RequestBody User user) {

        User userSaved = userRepository.save(user);
        return new ResponseEntity < > (userSaved, HttpStatus.OK);
    }
}

用户存储库

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

}

为什么 user_details 表中的 user_id 列被存储为空?

下面是我的卷发:

curl - X POST\
http: //localhost:5000/users \
    -H 'Cache-Control: no-cache'\ -
    H 'Content-Type: application/json'\ -
    H 'Postman-Token: 22a98f2b-d3cc-4127-b3ad-35f28c916fa4'\ -
    d '{
"description": "Some user",
"userDetails": {
    "description": "Some user details"
    }
}

【问题讨论】:

    标签: spring-boot hibernate jpa one-to-one


    【解决方案1】:

    您的映射不合适。关系的所有者是UserDetails。所以关系应该存在于UserDetailsEntity 中。

    找到下面添加的映射。

    用户实体

    @Entity
    @Table(name = "user")
    @Getter
    @Setter
    @NoArgsConstructor
    public class User {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
        private UserDetails userDetails;
    
        @Column(name = "description")
        private String description;
    
        public User(final String description) {
            this.description = description;
        }
    }
    

    UserDetails 实体

    @Entity
    @Table(name = "user_details")
    @Getter
    @Setter
    @NoArgsConstructor
    public class UserDetails {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "description")
        private String description;
    
        @OneToOne
        @JoinColumn(name = "user_id")
        private User user;
    
        public UserDetails(final String description) {
            this.description = description;
        }
    }
    

    【讨论】:

    • 另外,上述方法应该是正确的,并且有更简单的方法来代替使用关联,如果需要,您可以使用高级休眠@Embedded &amp; @Embedable feature 我也可以向您展示一个简单的示例.
    • @Amit Mishra,但对于@Embedded &amp; @Embedable feature,它不会将嵌入式类视为一个单独的实体。在这里,我们有两个表显示它的数据库
    • 你说的很对,我只是想分享一下,这也是一个很好的方法
    • @SSK 为什么说所有者是user_details。我想要两个表,其中 user 是父表,user_details 是子表,这样 user_details 中有一个名为 user_id 的列,它是映射到用户表 id 的外键。那么,这不是让“用户”成为所有者吗?
    • @SSK 我尝试了您的更改。出了两件事:1)创建的表,我在 user_details 表中看不到外键约束(我已删除 flyway 并使用 jpa auto create )。我需要 user_details 中的外键约束 2)当我点击上面给出的 curl 时,user_details 中的凭证 ID 列再次为空。
    【解决方案2】:

    在某些情况下,您希望在实体之间保留一些共同的细节。例如,您有一个表 DepartmentUser 和其他 User_address 并且您还有一个表 ManagementUser 并且在此表中您还想映射用户地址,因为这两种类型的用户都会有地址,您可能想要在这种情况下使用关联!但是 Hinbernate 确实有一个很棒的功能,叫做Embedding entity。您可以简单地将用户地址嵌入到您需要放入的每个实体中。

    这可以通过这种方式完成。

    @Entity
    class DepartmentUser{
       @Id
       @GeneratedValues(strategy = GenerationType.IDENTITY)
       private Long id;
       private String name;
       private String eamil;
       @Embedded
       private UserAddress address;
    
    //Standard setters and getters
    }
    

    另一个表用户地址

    @Embaddable
    class UserAddress{
      private String state;
      private int zip;
      private String country;
    
    //Standard setters and Getters
    }
    

    这只会将您的部门用户数据库附加到 UserAddress 中的列中,这也会带来良好的性能。

    【讨论】:

      猜你喜欢
      • 2019-11-08
      • 2020-12-17
      • 2020-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 2021-09-15
      相关资源
      最近更新 更多