【问题标题】:Mapping object's related entities by other field than ID通过 ID 以外的其他字段映射对象的相关实体
【发布时间】:2020-09-30 15:12:56
【问题描述】:

我正在使用以下实体:

@Entity
@Table(name = "books")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @ManyToOne
    private User user;
    private UUID uuid = UUID.randomUUID();
}

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String email;
    private String firstName;
    private String lastName;
    private String password;
    @OneToMany(mappedBy = "user")
    private List<Book> books;
    private UUID uuid = UUID.randomUUID();
}

以及以下 DTO:

public class NewBookRequest {
    private UUID userUuid;
}

和转换器:

@Component
public class NewBookRequestToEntityConverter implements Converter<NewBookRequest, Book> {

    private final ModelMapper modelMapper;

    public NewBookRequestToEntityConverter(final ModelMapper modelMapper) {
        this.modelMapper = modelMapper;
    }

    @Override
    public Book convert(@NotNull final NewBookRequest source) {
        return modelMapper.map(source, Book.class);
    }
}

还有部分服务代码:

public void addBook(final NewBookRequest newBookRequest) {
    final Book newBook = newBookRequestToEntityConverter.convert(newBookRequest);
    bookRepository.save(newBook);
}

当我尝试保存转换后的 Book 实体时,我得到了 ConstraintViolationException 异常,因为 newBook.user.id 为空。但是,正确分配了 newBook.user.uuid。有没有办法通过它的 uuid 自动映射 newBook 的用户?或者唯一的解决方案是这样做:

向转换器添加新方法:

@Component
public class NewBookRequestToEntityConverter implements Converter<NewBookRequest, Book> {

    private final ModelMapper modelMapper;

    public NewBookRequestToEntityConverter(final ModelMapper modelMapper) {
        this.modelMapper = modelMapper;
    }

    @Override
    public Book convert(@NotNull final NewBookRequest source) {
        return modelMapper.map(source, Book.class);
    }

    public Book convert(@NotNull final NewBookRequest source, final User user) {
        Book target = modelMapper.map(source, Book.class);
        target.setUser(user);
        return target;
    }
}

并修改服务代码:

public void addBook(final NewBookRequest newBookRequest) {
    final User user = userRepository.getUserByUuid(newBookRequest.getUserUuid());
    final Book newBook = newBookRequestToEntityConverter.convert(newBookRequest, user);
    bookRepository.save(newBook);
}

?感谢您的帮助!

【问题讨论】:

  • 我喜欢有人给你的帖子 -1 却没有给出任何解释

标签: java spring spring-data modelmapper


【解决方案1】:

在 Book 或 User 实体中,您可以使用 UUID 作为主键。你试过吗?

@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(
    name = "UUID",
    strategy = "org.hibernate.id.UUIDGenerator",
)
@Column(name = "id", updatable = false, nullable = false)
private UUID id;

但是,在某些数据库上,如果负载很高,则在使用基于 UUID 的索引时可能会出现性能问题。

【讨论】:

  • 问题是我不想使用 UUID 作为主键。 UUID 与 ID 一起使用
【解决方案2】:

我认为问题是您的转换器没有初始化User 的主键。 您可以更改User类中id字段的类型,因为回答https://stackoverflow.com/a/64141178/14225495,或者添加注释

@JoinColumn(name = "user_uuid", referencedColumnName = "uuid")

Book 类中的user 字段。在这种情况下,您还应该在books 表中添加列"user_uuid",确保users.uuid 列是唯一的并且不能为空来创建外键。

【讨论】:

  • 但问题是 UUID 与 ID 一起使用...
  • 您需要一列用于关联。此列必须在@JoinColumn 中指定,并且此列应为外键。您可以选择iduuid
  • 由于您从客户端收到用户 uuid,我建议使用uuid
猜你喜欢
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 2014-01-17
  • 2015-05-28
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多