Spring Data JPA@ManyToOne注解

x33g5p2x  于2022-10-25 转载在 Spring  
字(2.9k)|赞(0)|评价(0)|浏览(1046)

让我们学习如何在Spring Data JPA中使用@ManyToOne注解,并以Spring引导应用程序为例。

什么是多对一关系?

多对一Map或关联意味着一个父记录可以有多个子记录。换句话说,一个表的多个记录可以将它们自己与另一个表中的一个公共记录相关联。
例如,账户与分行实体的关系遵循多对一Map。因为多个账户可以Map到一个分行,但反之亦然。


属于银行单个分行的多个账户

Spring Data JPA中的@ManyToOne注解

JPA允许您使用@ManyToOne注解定义实体类之间的多对一关系。例如,在此处查看Account和Branch表的记录。

insert into branch (id, branch_name, branch_code)
values (1, 'South West branch', '6000000021');

insert into account (id, account_number, branch_id, full_name, balance)
values (1, '1231231231', 1, 'John1 Doe1', 100.23),
       (2, '1231231232', 1, 'John2 Doe2', 201.76),
       (3, '1231231233', 1, 'John3 Doe3', 403200.00),
       (4, '1231231234', 1, 'John4 Doe4', 10120.44),
       (5, '1231231235', 1, 'John5 Doe5', 43540.13);
Code language: SQL (Structured Query Language) (sql)

如您所见,“many”账户记录Map到“one”分支记录。让我们为这些表编写实体。

@Entity
public class Branch {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;
    String branchCode;
    String branchName;
    // Getters and Setters
}
Code language: Java (java)
@Entity
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;
    String accountNumber;
    String fullName;
    BigDecimal balance;

    @ManyToOne
    Branch branch;

    // Getters and Setters
}
Code language: Java (java)

如您所见,我们包含了Branch对象本身,而不是“Branch_id”。我们还将此对象字段标记为@ManyToOne。通过使用此注解,我们让SpringDataJPA知道这是一个具有多对一关系的连接。因此,当JPA对此进行评估时,它将找到并Map整个分支对象,而不仅仅是branch_id。
通过进行多对一Map,每当我们查询Account实体时,我们还可以保存有关其Branch详细信息的信息。
例如,让我们为Account实体编写SpringJpaRepository接口。我们还添加了一个查询,以按ID查找每个帐户。

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

    @Query("select a from Account a where a.accountNumber = ?1")
    public Account findAccount(String accountNumber);

}
Code language: Java (java)

让我们在服务和控制器层中使用这个存储库来显示结果。

@Service
public class AccountService {

    private final AccountRepository accountRepository;

    public AccountService(AccountRepository accountRepository){

        this.accountRepository = accountRepository;
    }
    public Account getAccount(String accountNumber){
        return  accountRepository.findAccount(accountNumber);
    }
}
Code language: Java (java)
@RestController
public class AccountController {

    private AccountService accountService;

    public AccountController(AccountService accountService) {

        this.accountService = accountService;
    }

    @GetMapping(path = "/accounts/{accountNumber}")
    public Account getAccount(@PathVariable("accountNumber") String accountNumber) {
        return accountService.getAccount(accountNumber);
    }
}
Code language: Java (java)

现在我们可以在控制器上测试响应,并看到分支对象也作为响应的一部分出现。


多对一Map正在运行
如果启用JPASQL日志,您可以看到在此请求过程中激发的SQL查询。

所以这里发生的事情是,应用程序首先加载了与帐号匹配的Account记录。但是,由于Account记录也需要Branch实体的详细信息,因此需要对Branch表进行第二次查询。

多对一Map和Spring JPA查询(JPQL)

正如我们刚才看到的,@ManyToOne执行两个查询来加载我们期望的数据。但我们可以完全通过JPQL连接获取来避免这种情况。为了演示这一点,我们需要用连接重写JPA方法,如下所示。

@Query("select a from Account a join fetch a.branch where a.accountNumber = ?1")
    public Account findAccount(String accountNumber);
Code language: Java (java)

通过故意指示JPQL连接获取记录,我们可以在一个数据库查询中收集所有详细信息。


JPA使用连接获取在单个查询中加载所有@ManyToOneMap
正如您在这个屏幕截图中看到的,DB请求仅使用内部连接发生一次。Spring JPA将解析SQL结果集并相应地创建对象。

总结

到目前为止,我们已经了解了什么是多对一关系,以及如何在春季JPA项目中实现它们。您可以在GitHub repository中找到此示例Spring引导应用程序。

相关文章

微信公众号

最新文章

更多