我似乎对JPA Repositories如何工作感到困惑。 在坚果壳
@Entity
public class User extends AbstractEntity {
protected final static String FK_NAME = "USER_ID";
@Column(nullable = false)
private String firstName;
@OneToMany(cascade = ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "userId")
private List<Detail> details = new ArrayList<Detail>();
}
@Entity
public class Detail extends AbstractEntity {
Long userId;
String hello;
}
@Repository
public interface UserRepository extends CrudRepository<User, Long> {
User findByFirstName(@Param("firstName") String firstName);
}
这是应用程序中唯一的控制器:
@RestController
public class Home {
@Autowired
UserRepository userRepository;
@Autowired
DetailsRepository loanRepository;
@RequestMapping(value = "")
public HttpEntity home() {
User user = userRepository.findByFirstName("John");
if (user == null) {
user = new User();
user.setFirstName("John");
}
Detail detail = new Detail();
detail.setHello("Hello Msh");
user.getDetails().add(detail);
userRepository.save(user);
return new ResponseEntity("hi", HttpStatus.OK);
}
}
在调试会话的屏幕截图下方,应用程序刚刚启动,并且对home()方法的get请求创建了新用户,新细节,为用户添加了详细信息。
下面的示例 - 保存用户后,详细信息实体会更新
现在,在下一个请求中,找到旧用户John并添加了一个新的详细实例。
旧用户已保存,但现在新创建的详细信息无法在外部更新。
为什么这只能第一次起作用?
答案 0 :(得分:1)
基本上这么多失败了,所以我建议你倒退一步。如果你是wana,那么就找到解决这个问题的简短方法继续阅读;)
第一部分与Jaiwo99的答案有关: 正如我在intellij的gradle视图中看到的那样,你使用的是Spring Boot。因此,有必要在配置类之上放置@EnableTransactionManagement。否则@Transacion注释没有任何效果。
第二部分是您的JPA / Hibernate模型映射。网上有这么多不好的做法,难怪大多数初学者都会遇到麻烦。
正确的版本可能看起来像(未经测试)
@Entity
public class User extends AbstractEntity {
@Column(nullable = false)
private String firstName;
@OneToMany(cascade = ALL, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy="user")
private List<Detail> details = new ArrayList<Detail>();
public void addDetail(Detail detail) {
details.add(detail);
detail.setUser(user);
}
}
@Entity
public class Detail extends AbstractEntity {
@ManyToOne
private User user;
private String hello;
public void setUser(User user){
this.user = user;
}
}
与创建模型映射相关的一些一般性建议:
答案 1 :(得分:0)
很简单,第一次在hibernate会话之外保存一个新实体,第二次,你得到的用户对象是一个分离的对象,默认情况下hibernate不会认为它在这种情况下被改变了。
*解决方案* 将此逻辑移动到另一个使用@transactional注释的服务类 要么 使用事务性注释您的控制器 要么 在用户类上覆盖equals和hashCode方法也可以提供帮助