我正在继续开发一个系统,该系统在前端使用React JavaScript库(及相关内容),在后端使用Spring Data REST,Hibernate,PostgreSQL及相关内容。
该系统将由拥有一个或多个公司及其客户的人使用。这意味着大多数/所有模型对象都将引用它们所属的Company
(ies)。此外,公司所有者将拥有一些Employee
s,这些Employee
将在此系统上具有更高级别的访问权限(或者这些将是所有者自己)。
我需要实现一种功能,当公司插入数据库时,也会插入员工。此外,如果一个失败,两者都必须失败。由于模型的设置方式,我发送一个Company
对象进行保存,并在其中发送新的employee: {
// ...,
company: {
// ....
}
}
,就像这样(使用Axios):
save
问题是,当在后端调用Company
方法时,Employee
对象的null
成员是Employee
。我尝试过一些事情,比如弄乱关系,在Company
对象中添加Company
列表,分别传递package xxx.model.common;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotNull;
import lombok.Data;
@Data
@MappedSuperclass
public abstract class Record {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
@NotNull
@Column(name = "deleted")
protected Boolean isDeleted = false;
@NotNull
@Column(name = "enabled")
protected Boolean isEnabled = true;
}
对象,但没有任何效果。
我还能尝试什么?以下是一些课程:
package xxx.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import xxx.common.Record;
// ...
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper=false)
@Entity
@Table(name="company")
@AttributeOverrides( { @AttributeOverride(name = "id", column = @Column(name = "id_company")) } )
public class Company extends Record {
/*
* ...
*/
// Necessary for Hibernate
protected Company() {}
public Company(/* ... */) {
/*
* ...
*/
}
}
package xxx.model.common;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper=false)
@MappedSuperclass
public abstract class Registry extends Record {
@NotBlank
@Column(name = "code", length = 15)
protected String code;
@NotBlank
@Column(name = "name", length = 40)
protected String name;
}
package xxx.model.common;
import javax.persistence.CascadeType;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import com.fasterxml.jackson.annotation.JsonBackReference;
import xxx.model.Company;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper=false)
@MappedSuperclass
public class RegistrySingleCompany extends Registry {
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE }, optional= false)
@JoinColumn(name="id_company")
protected Company company;
}
package xxx.model;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import xxx.model.common.RegistrySingleCompany;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper=false)
@Entity
@Table(name="employee")
@AttributeOverrides( { @AttributeOverride(name = "id", column = @Column(name = "id_employee")) } )
public class Employee extends RegistrySingleCompany {
/*
* ...
*/
// Necessary for Hibernate
protected Employee() {}
}
package xxx.repository.custom;
import org.springframework.data.repository.query.Param;
import xxx.model.Employee;
public interface EmployeeRepositoryCustom {
<S extends Employee> S save(S entity);
}
package xxx.repository.custom;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestBody;
import xxx.model.Employee;
public class EmployeeRepositoryCustomImpl implements EmployeeRepositoryCustom {
@Override
@Transactional
public <S extends Employee> S save(@RequestBody S entity) {
/*
* ...
*/
return entity;
}
}
package xxx.model.projection;
import org.springframework.data.rest.core.config.Projection;
import xxx.model.Employee;
@Projection(name = "employeeProjection", types = { Employee.class })
public interface EmployeeProjection {
Boolean getIsDeleted();
Boolean getIsEnabled();
String getCode();
String getName();
/*
* ...
*/
}
package xxx.repository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import xxx.model.Employee;
import xxx.model.projection.EmployeeProjection;
import xxx.repository.custom.EmployeeRepositoryCustom;
@RepositoryRestResource(collectionResourceRel = "employee", path = "employees", excerptProjection = EmployeeProjection.class)
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long>, EmployeeRepositoryCustom {}
conda is a pip replacement
提前致谢。
修改:添加了缺失的课程。
答案 0 :(得分:0)
如前所述,我尝试过的一件事是在Employee
对象中添加Company
列表,这意味着使用Company
的存储库而不是Employee
保存两个对象的是一个,但另一个对象也是null。但是,我的同事发现,通过在exported = false
内使用@RepositoryRestResource()
,可以正确接收该值。
那会搞砸其他事情,所以我们找到了以下临时解决方案:
exported = false
存储库(EmployeeWrapper
),其唯一目的是提供必要的Employee
数据,以便在save
内构建新数据库。Employee
内添加Company
列表,而是添加EmployeeWrapper
列表。EmployeeWrapper
也引用Company
。我们仍在努力采用更正确的方法。
更新:更正确的方法:
我的同事还发现,通过向@Transient
添加Employee
Company
列表,可以收到正确填写的Employee
对象以保存它。我不知道它是否在存储库中有效,因为由于其他限制,我们开始使用@RepositoryRestController
并且正在接收Company
作为@RequestBody org.springframework.hateoas.Resource<Company> resource
。
我们仍然希望找到更好的解决方案,因为Employee
中的Company
列表未在我们的模型中进行规划,更糟糕的是,我们需要将其他内容列表用于其他方法
更新:更好的方法:
再尝试一下,我们创建了一个POJO,其中包含我们需要的实体,并在控制器中以与以前相同的方式接收这些实体。效果很好。
但是,我们仍然不满意。理想情况下,我们希望收到要保存的Employee
,并将Company
保存在其中,并立即保存。