我找不到我问题的答案,希望这不是一个重复的问题。下面是一个虚构的例子。
数据库模型
数据表“用户”:
+--+--------+
|id|username|
+--+--------+
|1 |someUser|
+--+--------+
我想知道什么时候有什么不同:
1.实体(联系人)以“userId”Map为外键值(例如1)的方式保存到数据库
1.实体(联系人)保存到数据库中的方式是使用“userId”从数据库中检索相应的用户实体,并设置为联系人。
控制器
@RestController
public class ContactController {
// to keep is short, all action is here in controller
@Resource
private ContactMapper contactMapper;
@Resource
private ContactRepository contactRepository;
@Resource
private UserRepository userRepository;
@PostMapping("/as-foreign-key")
public void addContactWithUserIdForeignKey(@RequestBody ContactDto dto) {
Contact contact = contactMapper.contactDtoToContact(dto);
contactRepository.save(contact);
}
@PostMapping("/as-entity")
public void addContactWithUserEntity(@RequestBody ContactDto dto) {
User user = userRepository.findById(dto.getUserId()).get();
Contact contact = contactMapper.contactDtoToContact(dto);
contact.setUser(user);
contactRepository.save(contact);
}
}
DTO
@Data
public class ContactDto implements Serializable {
private final String firstName;
private final String lastName;
private final Integer userId;
}
MapStructMap器
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring")
public interface ContactMapper {
@Mapping(source = "userId", target = "user.id")
Contact contactDtoToContact(ContactDto contactDto);
}
实体
第一个
正在执行两个请求:
第一个
结果
数据表“联系人”:
+--+----------+---------+-------+
|id|first_name|last_name|user_id|
+--+----------+---------+-------+
|1 |John |Doe |1 |
|2 |Jane |Done |1 |
+--+----------+---------+-------+
两种方法产生相同的结果。
从控制台上看,我可以看到下面的hibSQL语句。
Hibernate: select user_.id, user_.username as username2_1_ from "user" user_ where user_.id=?
Hibernate: insert into contact (first_name, last_name, user_id) values (?, ?, ?)
Hibernate: select user0_.id as id1_1_0_, user0_.username as username2_1_0_ from "user" user0_ where user0_.id=?
Hibernate: insert into contact (first_name, last_name, user_id) values (?, ?, ?)
到目前为止我一直认为正确的方法是第二种方法:首先,找到实体(用户),使用setter,然后保存。
这两种方法在技术上有什么区别吗?我可以安全地走第一种方法吗?还是有什么我应该考虑的?
任何关于这个主题的信息都非常感谢。
1条答案
按热度按时间yqlxgs2m1#
实际上,我很惊讶1)能起作用,因为您正在使用一个分离的实体对象来进行关联。除非您的Map器或存储库实现以某种方式神奇地调用
EntityManager.find(User.class, dto.userId)
,否则我认为您应该选择3),即根本不加载用户,而是通过userRepository.getOne(dto.getUserId())
获取一个托管代理。