无法使用Spring引导JPA从MySQL检索数据



在程序开始从数据库检索数据的那一行,特别是从代码recordDB.setAccountName(billing.getAccountId().getAccountName());开始,我得到了一个java.lang.NullPointerException错误。实体表连接在一起,起初我认为它无法从其他表中检索数据,但我尝试仅使用recordDB.setAmount(billing.getAmount());运行。有人能解释我遗漏了什么吗?或者逻辑有问题吗?

组件

@Component
public class FileProcessor {
@Autowired
private BillingRepository billingRepository;

public FileProcessor() {
}

public List<Record> retrieveRecordfromDB(List<Request> requests) throws BarsException{
List<Record> records = new ArrayList<>();
if (!requests.isEmpty()) {
for (Request request : requests) {
Billing billing = billingRepository
.findByBillingCycleAndStartDateAndEndDate(
request.getBillingCycle()
, request.getStartDate()
, request.getEndDate());

if (billing == null) {
throw new BarsException(BarsException.NO_RECORDS_TO_WRITE);
}
Record recordDB = new Record();
recordDB.setBillingCycle(request.getBillingCycle());
recordDB.setStartDate(request.getStartDate());
recordDB.setEndDate(request.getStartDate());
recordDB.setAccountName(billing.getAccountId().getAccountName());
recordDB.setFirstName(billing.getAccountId().getCustomerId().getFirstName());
recordDB.setLastName(billing.getAccountId().getCustomerId().getLastName());
recordDB.setAmount(billing.getAmount());
records.add(recordDB);
}
}
return records;
}
}

账户实体

@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "account_id")
private int accountId;
private String accountName;
private LocalDateTime dateCreated;
private String isActive;
private String lastEdited;

public Account() {
}
public int getAccountId() {
return accountId;
}
public void setAccountId(int accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public LocalDateTime getDateCreated() {
return dateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
this.dateCreated = dateCreated;
}
public String getIsActive() {
return isActive;
}
public void setIsActive(String isActive) {
this.isActive = isActive;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
public Customer getCustomerId() {
return customerId;
}
public void setCustomerId(Customer customerId) {
this.customerId = customerId;
}
public Set<Billing> getBilling() {
return billing;
}
public void setBilling(Set<Billing> billing) {
this.billing = billing;
}
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "customer_id")
private Customer customerId;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "account_id")
private Set<Billing> billing;
}

计费实体

@Entity
public class Billing {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "billing_id")
private int billingId;
//private int billingId;
private int billingCycle;
private String billingMonth;
private Double amount;
private LocalDate startDate;
private LocalDate endDate;
private String lastEdited;
//private Account accountId;
public Billing() {
}
public int getBillingId() {
return billingId;
}
public void setBillingId(int billingId) {
this.billingId = billingId;
}
public int getBillingCycle() {
return billingCycle;
}
public void setBillingCycle(int billingCycle) {
this.billingCycle = billingCycle;
}
public String getBillingMonth() {
return billingMonth;
}
public void setBillingMonth(String billingMonth) {
this.billingMonth = billingMonth;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public LocalDate getStartDate() {
return startDate;
}
public void setStartDate(LocalDate startDate) {
this.startDate = startDate;
}
public LocalDate getEndDate() {
return endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
public Account getAccountId() {
return accountId;
}
public void setAccountId(Account accountId) {
this.accountId = accountId;
}
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "account_id")
private Account accountId;
}

客户实体

@Entity
public class Customer {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "customer_id")
private int customerId;
private String firstName;
private String lastName;
private String address;
private String status;
private LocalDateTime dateCreated;
private String lastEdited;
public Customer() {
}
public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public LocalDateTime getDateCreated() {
return dateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
this.dateCreated = dateCreated;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "customer_id")
private Set<Account> account;
}

存储库

@Repository
public interface BillingRepository extends JpaRepository<Billing, Integer> {

public Billing findByBillingCycleAndStartDateAndEndDate (int billingCycle, LocalDate startDate, LocalDate endDate);
}
  • 您的命名是不直观的,这会阻碍不熟悉代码的人:

  • recordDB意味着它是记录的数据库。相反,它是一个要保存在数据库中的记录。将其命名为";CCD_ 5";或者类似的要好得多,因为它能传达意图。

  • getAccountId()表示返回帐户的id(int或long(,而不是返回帐户本身。您应该将其重命名为getAccount()

关于问题:

您正在使用的双向ManyToOne&lt-&gt;CCD_ 9关系。

一方应该是关系的拥有方。此处应说明@JoinColumn。接收端应具有MappedBy属性。

有关详细信息,请参阅本指南:https://thorben-janssen.com/hibernate-tips-map-bidirectional-many-one-association/

它应该可以解决这个问题,因为只有连接表的数据检索似乎不起作用,因此修复引用应该可以解决问题。

您的billing.getAmount()确实引用了写入计费对象/表中的数据,而不是来自像billing.getAccountId().getAccountName()这样的另一个表,后者从连接到计费表的帐户表中获取数据。

最后但并非最不重要的是:

想想你的级联策略。按照目前的工作方式,删除一个账单将删除该账单的账户,这将删除那里的所有引用,以此类推,因为您目前对所有条目使用Cascade.All。这太糟糕了。

以下是级联指南:https://howtodoinjava.com/hibernate/hibernate-jpa-cascade-types/

您确定Billing类中的字段名称与数据库列名完全匹配吗?我看到您将列名设置为";billing_id";显式用于id字段,但不用于任何其他字段。我的猜测是,该类中的字段都为null,因为没有相应的数据库列(调试以确认(。

最新更新