【问题标题】:How to make related entity's id(auto-incremented) to be inserted when using one to one relationship in spring-data-jdbc?在spring-data-jdbc中使用一对一关系时如何插入相关实体的id(自动递增)?
【发布时间】:2021-10-17 17:54:51
【问题描述】:

我有两个表,它们是 profile_info 和 user_Info。 数据库ER图

表创建:

CREATE TABLE `user_info` (
  `id` int NOT NULL AUTO_INCREMENT,
  `userLogin` varchar(20) DEFAULT NULL,
  `userPassword` varchar(60) DEFAULT NULL,
  `userType` enum('user','administrator') DEFAULT NULL,
  `userEmail` varchar(320) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `userEmail` (`userEmail`)
);
CREATE TABLE `profile_info` (
  `id` int NOT NULL AUTO_INCREMENT,
  `userId` int DEFAULT NULL,
  `userRegistrationDate` datetime DEFAULT NULL,
  `userFirstName` varchar(25) DEFAULT NULL,
  `userSurName` varchar(25) DEFAULT NULL,
  `accountBalance` double DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `userUniqueId` (`userId`),
  CONSTRAINT `fkUserId` FOREIGN KEY (`userId`) REFERENCES `user_info` (`id`) ON DELETE CASCADE,
  CONSTRAINT `chk_accountBalance` CHECK ((`accountBalance` >= 0))
);

所以我有一对一的关系(一个配置文件只与一个用户相关)

这是我的实体:

用户:

@Table("user_info")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Persistable<Integer> {
    @Id
    @Column("id")
    private Integer id;
    @Column("userLogin")
    private String userLogin;
    @Column("userPassword")
    private String userPassword;
    @Column("userType")
    private String userType;
    @Column("userEmail")
    private String userEmail;
    @Override
    public boolean isNew() {
        return id==null;
    }
}

简介:

@Table("profile_info")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Profile implements Persistable<Integer> {
    @Id
    @Column("id")
    private Integer id;
    @Column("userRegistrationDate")
    private LocalDateTime userRegistrationDate;
    @Column("userFirstName")
    private String userFirstName;
    @Column("userSurName")
    private String userSurName;
    @Column("accountBalance")
    private double accountBalance;
    @MappedCollection(idColumn = "id")
    private User user;
    @Override
    public boolean isNew() {
        return id==null;
    }
}

我使用标准存储库作为 CRUDRepository 用户存储库:

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

配置文件存储库:

@Repository
public interface ProfileRepository extends CrudRepository<Profile,Integer> {
}

我有那个弹簧配置:

@Configuration
@EnableJdbcRepositories("com.example.testrepositories.repository")
public class ApplicationConfig extends AbstractJdbcConfiguration {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource managerDataSource = new DriverManagerDataSource();
        managerDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        managerDataSource.setUrl("jdbc:mysql://localhost:3306/testdatabase");
        managerDataSource.setUsername("Bruce");
        managerDataSource.setPassword("givanchy");
        return managerDataSource;
    }
    @Bean
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

我测试存储库的主要方法:

 public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
        ProfileRepository repository = context.getBean("profileRepository",ProfileRepository.class);
        User user = new User(null,"TestLogin","testPassword","user","eeed");
        Profile profile = new Profile(null, LocalDateTime.now(),"fff","sss",250.0,user);
        Profile savedProfile = repository.save(profile);
        System.out.println(savedProfile.getId());
        System.out.println(savedProfile.getUser().getId());
    }

输出是:

在这些操作之后我在数据库中:

用户信息已按原样插入

但是在配置文件中没有插入 userId,它应该这样工作吗?

编辑

我将根实体从 Profile 更改为 User,效果很好

用户实体:

@Table("user_info")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Persistable<Integer>{
    @Id
    @Column("id")
    private Integer id;
    @Column("userLogin")
    private String userLogin;
    @Column("userPassword")
    private String userPassword;
    @Column("userType")
    private String userType;
    @Column("userEmail")
    private String userEmail;
    @MappedCollection(keyColumn = "id",idColumn = "userId")
    private Profile profile;
    @Override
    public boolean isNew() {
        return id==null;
    }
}

个人资料实体:

@Table("profile_info")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Profile  implements Persistable<Integer>{
    @Id
    @Column("id")
    private Integer id;
    @Column("userRegistrationDate")
    private LocalDateTime userRegistrationDate;
    @Column("userFirstName")
    private String userFirstName;
    @Column("userSurName")
    private String userSurName;
    @Column("accountBalance")
    private double accountBalance;
    @Override
    public boolean isNew() {
        return id==null;
    }
}

【问题讨论】:

  • 您是否尝试过使用 JPA 注释而不是 @MappedCollection
  • @GovindaSakare 我使用的是 spring-data-jdbc 而不是 jpa

标签: java spring jdbc spring-data spring-data-jdbc


【解决方案1】:

似乎使用一对一的关系是错误的。根据您的 ER 图,每个 User 可以有多个 Profile 行。如果是这种情况并且Profile 是一个聚合(根),那么user_info 也是一个聚合根。建议为两个实体建立一个存储库。

因此,我们处理聚合之间的引用,这些引用应该仅由 id 表示,而不是对象引用。这意味着您应该在保存User 后将Profile.userIntegerAggregateReference&lt;Integer&gt; 设置为User.id 的值。

其他一些注意事项: MappedCollection 与简单引用无关。 当A 引用B 时,数据库中的外键方向相反。所以如果ProfileUser 确实有一对一的关系,User 应该是聚合根。

有关这一切的更多背景信息,请参阅https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates

【讨论】:

  • 我将用户设置为聚合根,如你所说,它有效
  • JdbcRepositoryFactory 是否支持示例查询?
猜你喜欢
  • 1970-01-01
  • 2019-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-03
  • 1970-01-01
相关资源
最近更新 更多