我有两个实体,即公司和用户。一家公司可以有很多用户。因此,当我保存公司时,它还会在一个事务中创建一个用户。但是,如果由于某种原因导致用户插入失败,我希望公司的插入应该回滚,目前这种情况不会发生。
公司实体:
@Entity
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
@Size(min = 4, max = 100)
private String name;
@Size(max = 500)
private String description;
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL)
@JsonManagedReference
private List<User> users = new ArrayList<>();
public Company() {
}
;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
用户实体:
@Entity
public class User implements UserDetails {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(length = 50, unique = true)
@NotNull
@Size(min = 4, max = 50)
private String username;
@NotNull
@Size(min = 8)
private String password;
@Column(length = 50)
@NotNull
@Size(min = 4, max = 50)
private String firstName;
@Column(length = 50)
@NotNull
@Size(min = 4, max = 50)
private String lastName;
@Column(length = 50, unique = true)
@NotNull
@Size(min = 4, max = 50)
private String email;
private Boolean enabled = true;
@Temporal(TemporalType.TIMESTAMP)
@UpdateTimestamp
private Date lastPasswordReset;
@Column(nullable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
@CreatedDate
private Date createdAt = new Date();
@Column(nullable = false)
@Temporal(TemporalType.TIMESTAMP)
@UpdateTimestamp
@LastModifiedDate
private Date updatedAt = new Date();
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
name = "user_authority",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "authority_id", referencedColumnName = "id")})
private List<Authority> roles;
@ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
@JsonBackReference
private Company company;
@Transient
@JsonIgnore
private Collection<? extends GrantedAuthority> authorities;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
/**
* Indicates whether the user's account has expired. An expired account cannot be
* authenticated.
*
* @return <code>true</code> if the user's account is valid (ie non-expired),
* <code>false</code> if no longer valid (ie expired)
*/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* Indicates whether the user is locked or unlocked. A locked user cannot be
* authenticated.
*
* @return <code>true</code> if the user is not locked, <code>false</code> otherwise
*/
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* Indicates whether the user's credentials (password) has expired. Expired
* credentials prevent authentication.
*
* @return <code>true</code> if the user's credentials are valid (ie non-expired),
* <code>false</code> if no longer valid (ie expired)
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* Indicates whether the user is enabled or disabled. A disabled user cannot be
* authenticated.
*
* @return <code>true</code> if the user is enabled, <code>false</code> otherwise
*/
@Override
public boolean isEnabled() {
return true;
}
public void setUsername(String username) {
this.username = username;
}
/**
* Returns the authorities granted to the user. Cannot return <code>null</code>.
*
* @return the authorities, sorted by natural key (never <code>null</code>)
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
if (this.getRoles() != null) {
return mapToGrantedAuthorities(this.getRoles());
}
return null;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
if (enabled == null) {
enabled = false;
}
this.enabled = enabled;
}
public Date getLastPasswordReset() {
return lastPasswordReset;
}
public void setLastPasswordReset(Date lastPasswordReset) {
if (lastPasswordReset == null) {
lastPasswordReset = new Date();
}
this.lastPasswordReset = lastPasswordReset;
}
public List<Authority> getRoles() {
return roles;
}
public void setRoles(List<Authority> roles) {
this.roles = roles;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
private List<GrantedAuthority> mapToGrantedAuthorities(List<Authority> authorities) {
return authorities.stream()
.map(authority -> new SimpleGrantedAuthority(authority.getName().name()))
.collect(Collectors.toList());
}
}
公司服务
@Service
public class CompanyService implements ICompanyService {
@Autowired
CompanyRepository companyRepository;
@Autowired
IUserService userService;
@Override
@Transactional
public Company save(Company company) {
try {
userService.initUserFromCompany(company);
return companyRepository.save(company);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
请求正文
{
"name" : "Evil Corp 2",
"description" : "Bad company",
"users" : [
{
"username" : "rambo",
"password" : "rambo_123",
"firstName" : "Slilvestor",
"lastName" : "Stelon",
"email" : "rambo@rambo.com"
}
]
}
因此,如果以某种方式,请求中传递的电子邮件已经存在,那么用户实体将不会被保存,因此在这种情况下我需要公司回滚。任何想法我怎么能实现这种行为?
答案 0 :(得分:0)
有几种方法可以解决这个问题。我会建议你一个,如果用户在表中有相同的电子邮件,则抛出RuntimeException。在userService方法中,我猜测是initUserFromCompany方法,如果有的话,抛出RuntimeException。在save方法中,您应该这样做:
@Override
@Transactional(rollbackFor=Exception.class)
public Company save(Company company) {
userService.initUserFromCompany(company);
return companyRepository.save(company);
}
有几个与回滚相关的帖子和答案。您可以查看this以获取详细说明。