gpt4 book ai didi

java - 为什么 Spring JPA 双向 OneToMany 和 ManyToOne 不更新外键列?

转载 作者:行者123 更新时间:2023-12-01 07:43:18 26 4
gpt4 key购买 nike

嗨,我正在使用 OneToMany 和 ManyToOne 双向关系学习 Spring JPA,在某些示例中,当我在两侧编写时,我看到 OneToMany 和 ManyToOne 关系,JPA 添加一个新列作为外键列,并从父表。但当我尝试我的时,该列始终是空白的。我的代码如下所示:

这是我的 Account.java 模型:

@Entity
@Table(name = "msAccount")
public class Account {

@Id
@NotBlank(message = "Not Blank")
@Size(min = 0, max = 20)
public String accountId;

@NotBlank(message = "Not Blank")
public String accountName;

@NotBlank(message = "Not Blank")
@Email(message = "Should be the right email")
public String accountEmail;

@NotBlank(message = "Not Blank")
@Size(min = 5, message = "Minimal 5 char")
public String accountAddress;

@NotBlank(message = "Not Blank")
public String town;

@NotBlank(message = "Not Blank")
public String npwp;

@NotBlank(message = "Not Blank")
public String phoneNumber;

public String fax;

public String remarks;

@NotNull
public Date entryTime;

@NotNull
public Boolean active;

@OneToMany(mappedBy="account", cascade = CascadeType.ALL, orphanRemoval = true)
public List<Dealer> dealer;

//getter setter skipped

}

这是我的 Dealer.java 模型:

@Entity
@Table(name = "msDealer")
public class Dealer {

@Id
@NotBlank(message = "Tidak Boleh Kosong")
@Size(min = 0, max = 20)
public String dealerId;

@NotBlank(message = "Tidak Boleh Kosong")
public String dealerName;

@NotBlank(message = "Tidak Boleh Kosong")
@Email(message = "Masukkan Email yang bener")
public String dealerEmail;

@NotBlank(message = "Tidak Boleh Kosong")
@Size(min = 5, message = "Minimal 5 karakter")
public String dealerAddress;

@ManyToOne(fetch = FetchType.LAZY)
public Account account;

//getter setter skipped

}

这是我的存储库:

@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {

}

这是我的服务:

@Service
public class AccountService {

@Autowired
private AccountRepository accountRepository;

public Account save(Account account) {
return accountRepository.save(account);
}

}

这是我的 Controller :

@RestController
@RequestMapping("/api/account")
public class AccountController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final int ROW_PER_PAGE = 10;

@Autowired
private AccountService accountService;

@PostMapping("/new")
public ResponseEntity<Account> addAccount(@Valid @RequestBody Account account) {
try {
Account newAccount = accountService.save(account);
return ResponseEntity.created(new URI("/api/account/" + newAccount.getAccountId()))
.body(account);
} catch(Exception ex) {
logger.error(ex.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
}

}

然后我将 JSON 发布到我的保存端点中:

{
"accountId": "USA001",
"accountName": "string",
"accountEmail": "string",
"accountAddress": "string",
"town": "string",
"npwp": "string",
"phoneNumber": "string",
"fax": "string",
"remarks": "string",
"entryTime": "2020-04-07T15:01:29.404Z",
"active": true,
"dealer": [
{
"dealerId": "MMO001",
"dealerName": "string",
"dealerEmail": "string",
"dealerAddress": "string"
}
]
}

当我保存它时,终端中显示的 hibernate 看起来正在将查询插入到这两个表中,但是当我检查我的数据库表(postgresql)时,我发现有一个字段“account_account_id”为空,什么我错过这里了吗?

我希望 Hibernate 像这样运行 sql :

insert into account (account_id, account_name, ...etc)
values ('USA001', 1)

insert into dealer (account_account_id, dealer_name, dealer_id, ...etc)
values ('USA001', 'New dealer 1', 'MMO001')

这是我经过一番尝试后更新的模型:

我的帐户.java我删除了cascade = CascadeType.ALL,orphanRemoval = true

@Entity
@Table(name = "msAccount")
public class Account {

@Id
@NotBlank(message = "Tidak Boleh Kosong")
@Size(min = 0, max = 20)
public String accountId;

@NotBlank(message = "Tidak Boleh Kosong")
public String accountName;

@NotBlank(message = "Tidak Boleh Kosong")
@Email(message = "Masukkan Email yang bener")
public String accountEmail;

@NotBlank(message = "Tidak Boleh Kosong")
@Size(min = 5, message = "Minimal 5 karakter")
public String accountAddress;

@NotBlank(message = "Tidak Boleh Kosong")
public String town;

@NotBlank(message = "Tidak Boleh Kosong")
public String npwp;

@NotBlank(message = "Tidak Boleh Kosong")
public String phoneNumber;

public String fax;

public String remarks;

@NotNull
public Date entryTime;

@NotNull
public Boolean active;

@OneToMany(mappedBy="account")
// @JoinColumn(name = "accountId")
public List<Dealer> dealer;

//getter setter skipped

}

这是我的 Dealer.java。添加了@JoinColumn:

@Entity
@Table(name = "msDealer")
public class Dealer {

@Id
@NotBlank(message = "Tidak Boleh Kosong")
@Size(min = 0, max = 20)
public String dealerId;

@NotBlank(message = "Tidak Boleh Kosong")
public String dealerName;

@NotBlank(message = "Tidak Boleh Kosong")
@Email(message = "Masukkan Email yang bener")
public String dealerEmail;

@NotBlank(message = "Tidak Boleh Kosong")
@Size(min = 5, message = "Minimal 5 karakter")
public String dealerAddress;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "account_id")
public Account account;

//getter setter skipped

}

现在错误变得很奇怪,我在保存 JSON 数据时收到此错误

> "Unable to find com.api.b2b.Model.Dealer with id MMO001; nested
> exception is javax.persistence.EntityNotFoundException: Unable to find
> com.api.b2b.Model.Dealer with id MMO001"

在一些教程中它有效,但我的却不行,我做错了什么?

这是我的 github 存储库:https://github.com/Fly-Away/LearningSpring

最佳答案

您缺少@JoinColumn在 child 方面:

@Entity
@Table(name = "ms_dealer")
public class Dealer {

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "account_account_id")
public Account account;

// other fields

}

您已使用mappedBy在父端,但在子端没有映射。您需要指出 Dealer是关系所有者 - 它具有外键。

编辑:如果您要保留(而不是合并)Account实体及其子实体,您不应传递子实体的 id。 (实际上,在持久化时传递任何 id 是一种代码味道,而且很可能是性能 killer 。)使用的 json 应该如下所示:

{
"accountName": "string",
"accountEmail": "string",
"accountAddress": "string",
"town": "string",
"npwp": "string",
"phoneNumber": "string",
"fax": "string",
"remarks": "string",
"entryTime": "2020-04-07T15:01:29.404Z",
"active": true,
"dealer": [
{
"dealerName": "string",
"dealerEmail": "string",
"dealerAddress": "string"
}
]
}

在保存之前可能还需要双方同步:

account.getDealer().forEach(d -> d.setAccount(account));

编辑:

来自 Author编辑必须级联到子级:

@OneToMany(mappedBy = "account", cascade = CascadeType.ALL, orphanRemoval = true)
public List<Dealer> dealer;

您还可以添加@JsonIgnore超过ActionList<Dealer>以避免序列化为 json 时发生堆栈溢出。

关于java - 为什么 Spring JPA 双向 OneToMany 和 ManyToOne 不更新外键列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61083247/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com