我目前正在使用GSON将以下JSON转换为两个java对象。 Company对象包含一对一关系的Accounts对象。
JSON:
{
"company_name": "ETHEREUM LTD",
"accounts": {
"next_made_up_to": "2018-11-30",
"next_due": "2019-08-31"
},
"company_number": "11090535"
}
公司对象:
@Data
@Entity
@Table(name = "companies")
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(cascade=CascadeType.ALL)
private Accounts accounts;
@NotNull
@SerializedName("company_number")
@Column(unique = true)
private String companyNumber;
@SerializedName("company_name")
private String companyName;
public Company() {}
public Company(String companyNumber) {
this.companyNumber = companyNumber;
}
}
帐户对象:
@Data
@Entity
@Table(name = "accounts")
public class Accounts {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@SerializedName("next_due")
private Date nextDue;
@SerializedName("next_made_up_to")
private Date nextMadeUpTo;
}
我已经实现了一个Spring Data JpaRepository来将这些对象保存到我的数据库中。
public interface CompanyRepository extends JpaRepository<Company, Long> {
}
我有一种方法可以使用新的JSON信息更新数据库中的所有Company对象。
@Scheduled(fixedRate = 50000)
public void updateAllCompanies() {
System.out.println("Starting update!");
for(Company company : companyRepository.findAll()) {
Long companyId = company.getId();
Long accountsId = null;
if(company.getAccounts() != null) {
accountsId = company.getAccounts().getId();
}
company = getCompany(company.getCompanyNumber());
company.setId(companyId);
if(accountsId != null) {
company.getAccounts().setId(accountsId);
}
companyRepository.save(company);
}
}
除非我在父对象和子对象上手动设置id,否则这些对象将创建为新的数据库条目,而不是更新现有条目。除了在Java中手动设置ID之外,还有更好的方法吗?
答案 0 :(得分:2)
除非我在父对象和子对象上手动设置id,否则这些对象将创建为新的数据库条目,而不是更新现有条目。
这就是每个持久性提供程序的工作方式。
如果实体的@Id
字段未被标记为由持久性提供程序或数据库自动生成,则空值的存在将触发提供程序抛出异常。但是,如果字段标记为由提供程序或数据库自动生成,则它将跳过该异常并将该实体视为必须插入的新实例。只有在标识符字段中存在值时,才会触发对现有行的更新。
除了在Java中手动设置ID之外,还有更好的方法吗?
这取决于。
如果JSON有效负载可以为您提供id值,您只需将这些值序列化到对象中,持久性过程就像您手动分配它们一样。这意味着将更新具有标识符值的实体,不会插入那些实体。
如果这不是一个合理的选项,那么如果您打算使用@Entity
代表Accounts
,则需要指定它们。
我不确定您的Accounts
实体是否是数据模型中其他任何内容的引用。但有一件事需要考虑的是,@ElementCollection
嵌入式内容可以很容易地解决您的标识符问题:
@Embeddable
public class Accounts implements Serializable {
private Date nextDue;
private Date nextMadeUpTo;
// implement proper equals/hashcode here
}
@Entity
public class Customer {
// your normal things
@ElementCollection
private Set<Accounts> Accounts;
}
现在您需要做的就是将JSON获得的任何数据添加到Accounts
并将其放入元素集合中。然后,Hibernate将使用如下所示的集合表来确定是否需要删除或插入某些内容:
CUSTOMER_ID | NEXT_DUE | NEXT_MADE_UP_TO
正确使用equals
/ hashCode
Accounts
嵌入保证不会重复,它也有助于确定修改或不修改的内容。底层集合表现在使用可嵌入+ Customer
主键的所有字段作为表的主键。通过将数据用作自然键,可以避免代理主键的问题。