复合主键的成员为关联实体

129 阅读2分钟
  • 实体类

一对多关系,并由Many处去管理管理关系

  • One处的实体类

    @Entity @Data public class ClientApp { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToMany(targetEntity = ClientAppModule.class,mappedBy ="clientApp" ) private List modules=List.of(); }

  • Many处的实体类

    @Data @Entity @IdClass(Key.class) public class ClientAppModule implements Serializable { @Id private Long authId; //权限id @ManyToOne @Id @JsonIgnoreProperties("modules") @JoinColumn(name = "client_app_id") private ClientApp clientApp;

    private LocalDateTime expiredTime;
    private ClientAppModuleStatus status;
    

    }

  • 再格外加一个idClass类 查询的时候需要

    @Data @NoArgsConstructor public class Key implements Serializable { private Long authId; //权限id private ClientApp clientApp; }

  • 数据层操作层

  • One处的Repository

    public interface ClientAppRepository extends JpaRepository<ClientApp, Long> { }

  • Many处的Repository

    public interface ClientAppModuleRepository extends JpaRepository<ClientAppModule, Key> { }

  • 操作方法

  • 保存One处的时候 由于关联关系由Many处去管理,所以非常简单

    @Test public void create(){ ClientApp clientApp = new ClientApp(); /* ..业务赋值..*/ clientAppRepository.save(clientApp); }

注意为什么要将保存Many处的对象单独来说 ,因为其 "复合主键成员为关联对象"的原因和普通的关系对象保存不一样。

如果是普通的一对多关联,你可以下下面操作

final ClientAppModule clientAppModule = new ClientAppModule();
clientAppModule.setAuthId(1L);
//方法一:
ClientApp clientApp = clientAppRepository.findById(1L).get();
//方法二:
//clientApp = new ClientApp();clientApp.setId(1L);
//设置关联关系
clientAppModule.setClientApp(clientApp);
clientAppModuleRepository.save(clientAppModule);

但是!!如果像一般的一对多去使用JpaRepository#save保存时 他会提示你

Cannot convert value of type 'java.lang.Long' to required type 'com.example.springdemo.entity.ClientApp' for property 'clientApp': no matching editors or conversion strategy found

由于鄙人愚笨 就只能 不使用SpringJpa,而使用EntityManager#persist、EntityManager#merge

  • 注意如果你传给many的One不是关联实体 就必要使用merge方法

        final ClientAppModule clientAppModule = new ClientAppModule();
        clientAppModule.setAuthId(1L);
        ClientApp clientApp=clientAppRepository.findById(1L).get();
        clientAppModule.setClientApp(clientApp);
        entityManager.persist(clientAppModule);
    
  • 而persist对one是不是持久化对象,都无所谓

        final ClientAppModule clientAppModule = new ClientAppModule();
        clientAppModule.setAuthId(1L);
        ClientApp clientApp=null;
        //方法一:
        //clientApp = clientAppRepository.findById(1L).get();
        //方法二:
        clientApp = new ClientApp();
        clientApp.setId(1L);
        //设置关联关系
        clientAppModule.setClientApp(clientApp);
        entityManager.merge(clientAppModule);
    

查询问题

和平常的一样 ,使用SpringJpa查询就行。

final Key id = new Key();
id.setAuthId(1L);
final ClientApp clientApp = new ClientApp();clientApp.setId(1L);
id.setClientApp(clientApp);
final ClientAppModule clientAppModule = clientAppModuleRepository.findById(id).get();

修改问题

调用save的时候还是报上面的错误

  • 你可以使用Jpa查询出来的对象是持久态,来操作。事务完成之后会自动提交(一定要在事务中)

    final Key id = new Key(); id.setAuthId(1L); final ClientApp clientApp = new ClientApp();clientApp.setId(1L); id.setClientApp(clientApp); final ClientAppModule clientAppModule = clientAppModuleRepository.findById(id).get(); clientAppModule.setStatus(ClientAppModuleStatus.ENABLE); //clientAppModuleRepository.save(clientAppModule); 会报错

  • 使用EntityManager#persist、EntityManager#merge.注意事项和保存的时候一样

    final ClientAppModule clientAppModule = new ClientAppModule(); clientAppModule.setAuthId(1L); final ClientApp clientApp = new ClientApp(); clientApp.setId(1L); // final ClientAppModule clientAppModule = clientAppModuleRepository.findById(id).get(); clientAppModule.setClientApp(clientApp); clientAppModule.setStatus(ClientAppModuleStatus.STOP); entityManager.merge(clientAppModule);

如果你有更好的方法去操作 麻烦大佬提个提示!!!