英文:
Mapping object's related entities by other field than ID
问题
我正在使用以下实体:
@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
为null。但是,newBook.user.uuid
被正确赋值。有没有自动按其uuid映射newBook的user的方法?或者唯一的解决方案是做像这样的事情:
添加新方法到转换器:
@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);
}
?谢谢任何帮助!
英文:
I am using the following entities:
@Entity
@Table(name = "books")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne
private User user;
private UUID uuid = UUID.randomUUID();
}
and
@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();
}
and the following DTO:
public class NewBookRequest {
private UUID userUuid;
}
and the converter:
@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);
}
}
and there is part of service code:
public void addBook(final NewBookRequest newBookRequest) {
final Book newBook = newBookRequestToEntityConverter.convert(newBookRequest);
bookRepository.save(newBook);
}
When I try to save the converted Book entity I get the ConstraintViolationException exception, as newBook.user.id
is null. However, newBook.user.uuid is correctly assigned. Is there any way to automatically map newBook's user by its uuid? Or the only solution is to do something like this:
add new method to converter:
@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;
}
}
and modify service's code:
public void addBook(final NewBookRequest newBookRequest) {
final User user = userRepository.getUserByUuid(newBookRequest.getUserUuid());
final Book newBook = newBookRequestToEntityConverter.convert(newBookRequest, user);
bookRepository.save(newBook);
}
? Thanks for any help!
答案1
得分: 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的索引可能会导致性能问题。
英文:
In Book or User entity you could use UUID as primary key. Did you try that?
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator",
)
@Column(name = "id", updatable = false, nullable = false)
private UUID id;
However on some databases there can be performance issue when using indexes based on UUID if there is high load.
答案2
得分: 1
我认为问题在于您的转换器未初始化 User
的主键。
您可以更改 User
类中 id
字段的类型,具体原因请参考 https://stackoverflow.com/a/64141178/14225495,或者在 Book
类中的 user
字段上添加注释:
@JoinColumn(name = "user_uuid", referencedColumnName = "uuid")
在这种情况下,您还应在 books
表中添加 user_uuid
列,确保 users.uuid
列是唯一的且不可为空,以创建外键。
英文:
I think problem is your converter does not initialize the primary key of User
.
You may either change the type of id
field in the User
class due to answer https://stackoverflow.com/a/64141178/14225495, or add the annotation
@JoinColumn(name = "user_uuid", referencedColumnName = "uuid")
to the user
field in the Book
class. In this case you should also add column "user_uuid"
in the books
table, make sure the users.uuid
column is unique and not nullable to create foreign key.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论