Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring JPA:如何使用两个外键处理实体映射,这两个外键一起充当主键_Spring_Hibernate_Spring Boot_Jpa - Fatal编程技术网

Spring JPA:如何使用两个外键处理实体映射,这两个外键一起充当主键

Spring JPA:如何使用两个外键处理实体映射,这两个外键一起充当主键,spring,hibernate,spring-boot,jpa,Spring,Hibernate,Spring Boot,Jpa,我有两张桌子: 表A id(PK) name ------------ 1 aa 2 ab 3 ac 4 ad 表B master_id(FK_id) slave_id(FK_id) 1 2 2 3 2 4 表A和B具有一对多关系。 如上图所示,表B有两列的复合键(master_id,slave_id)。表B中的两列都与表A有外键

我有两张桌子:

表A

id(PK)  name
------------
1       aa
2       ab
3       ac
4       ad
表B

master_id(FK_id)    slave_id(FK_id)
1                   2
2                   3
2                   4
表A和B具有一对多关系。 如上图所示,表B有两列的复合键(master_id,slave_id)。表B中的两列都与表A有外键关系


我们如何使用spring JPA/hibernate处理此实体映射?

A表的映射非常简单:

@Entity
public class A {

    @Id
    private Long id;

    private String name;

    // setters, getters, etc
}
对于B表,您必须声明多对一关系和复合id。对于
@EmbeddedId
,您不能将实体引用用作字段,因此在这种情况下
@IdClass
似乎更好:

@Entity
@IdClass(BId.class)
public class B {

    @Id
    @ManyToOne
    private A master;

    @Id
    @ManyToOne
    private A slave;

    // setters, getters, etc

}
最后一个,BId.class。同样,不能将实体引用用作字段,但它们可以替换为A.id类型(长):


如果您需要完全控制表B,那么ilinykhma的方法(
IdClass
)是好的(或者您可以使用
EmbeddedId

但是如果你“只是”需要“A之间的多对多主/从关系”

(表B的性质表明了这一点。)

…,那么这就更好了:

@Entity
public class A implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToMany
    @JoinTable(
            name = "B",
            joinColumns = @JoinColumn(name = "slave_id"),
            inverseJoinColumns = @JoinColumn(name = "master_id"))
    private List<A> myMasters;

    @ManyToMany(mappedBy = "myMasters")
    private List<A> mySlaves;

    private String name;
 // getter, setter, hashCode, equals...
}

测试:


输出:

...
      .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.2.RELEASE)

2020-01-11 17:29:53.400  INFO 10532 --- [           main] c.example.soq59695741.ApplicationTests   : Starting ApplicationTests on ******* with PID 10532 (started by **** in D:\***\***\***)
2020-01-11 17:29:53.403  INFO 10532 --- [           main] c.example.soq59695741.ApplicationTests   : No active profile set, falling back to default profiles: default
2020-01-11 17:29:53.927  INFO 10532 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-01-11 17:29:53.956  INFO 10532 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 15ms. Found 0 JPA repository interfaces.
2020-01-11 17:29:54.514  INFO 10532 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-01-11 17:29:54.806  INFO 10532 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-01-11 17:29:54.893  INFO 10532 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-01-11 17:29:54.973  INFO 10532 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.4.9.Final}
2020-01-11 17:29:55.184  INFO 10532 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-01-11 17:29:55.606  INFO 10532 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2020-01-11 17:29:56.327  INFO 10532 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-01-11 17:29:56.335  INFO 10532 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-01-11 17:29:56.509  INFO 10532 --- [           main] c.example.soq59695741.ApplicationTests   : Started ApplicationTests in 3.437 seconds (JVM running for 4.615)
2020-01-11 17:29:56.620  INFO 10532 --- [           main] o.s.t.c.transaction.TransactionContext   : Began transaction (1) for test context [DefaultTestContext@3a393455 testClass = ApplicationTests, testInstance = com.example.soq59695741.ApplicationTests@5829e4f4, testMethod = test@ApplicationTests, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@13518f37 testClass = ApplicationTests, locations = '{}', classes = '{class com.example.soq59695741.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7fd7a283, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@16612a51, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@47c81abf, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@6b0d80ed], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@2fa879ed]; rollback [true]
2020-01-11 17:29:56.796  INFO 10532 --- [           main] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test: [DefaultTestContext@3a393455 testClass = ApplicationTests, testInstance = com.example.soq59695741.ApplicationTests@5829e4f4, testMethod = test@ApplicationTests, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@13518f37 testClass = ApplicationTests, locations = '{}', classes = '{class com.example.soq59695741.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7fd7a283, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@16612a51, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@47c81abf, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@6b0d80ed], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.154 s - in com.example.soq59695741.ApplicationTests
2020-01-11 17:29:56.859  INFO 10532 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-01-11 17:29:56.859  INFO 10532 --- [extShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'
2020-01-11 17:29:56.861 ERROR 10532 --- [extShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000478: Unsuccessful: drop table a if exists
2020-01-11 17:29:56.870  INFO 10532 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2020-01-11 17:29:56.874  INFO 10532 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Results:

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 7.976 s

我以相同的方式将其插入到拥有的实体(仅A表)中,而不是映射到关联的实体(B表)
insert into A (id, name) 
values (1, 'aa'),
       (2, 'ab'),
       (3, 'ac'),
       (4, 'ad');

insert into B (master_id, slave_id)
values (1, 2),
       (2, 3),
       (2, 4);
@SpringBootTest
class ApplicationTests {

    @Autowired
    private EntityManager entityManager;

    @Test
    @Transactional
    void test() {
        assertThat(entityManager);
        A one = entityManager.find(A.class, 1L);
        assertThat(one);
        assertThat(one.getMyMasters().isEmpty());
        A two = entityManager.find(A.class, 2L);
        assertThat(two);
        assertThat(one.getMySlaves().contains(two));
        assertThat(two.getMyMasters().contains(one));
    }

}
...
      .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.2.RELEASE)

2020-01-11 17:29:53.400  INFO 10532 --- [           main] c.example.soq59695741.ApplicationTests   : Starting ApplicationTests on ******* with PID 10532 (started by **** in D:\***\***\***)
2020-01-11 17:29:53.403  INFO 10532 --- [           main] c.example.soq59695741.ApplicationTests   : No active profile set, falling back to default profiles: default
2020-01-11 17:29:53.927  INFO 10532 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-01-11 17:29:53.956  INFO 10532 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 15ms. Found 0 JPA repository interfaces.
2020-01-11 17:29:54.514  INFO 10532 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-01-11 17:29:54.806  INFO 10532 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-01-11 17:29:54.893  INFO 10532 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-01-11 17:29:54.973  INFO 10532 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.4.9.Final}
2020-01-11 17:29:55.184  INFO 10532 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-01-11 17:29:55.606  INFO 10532 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2020-01-11 17:29:56.327  INFO 10532 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-01-11 17:29:56.335  INFO 10532 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-01-11 17:29:56.509  INFO 10532 --- [           main] c.example.soq59695741.ApplicationTests   : Started ApplicationTests in 3.437 seconds (JVM running for 4.615)
2020-01-11 17:29:56.620  INFO 10532 --- [           main] o.s.t.c.transaction.TransactionContext   : Began transaction (1) for test context [DefaultTestContext@3a393455 testClass = ApplicationTests, testInstance = com.example.soq59695741.ApplicationTests@5829e4f4, testMethod = test@ApplicationTests, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@13518f37 testClass = ApplicationTests, locations = '{}', classes = '{class com.example.soq59695741.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7fd7a283, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@16612a51, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@47c81abf, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@6b0d80ed], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@2fa879ed]; rollback [true]
2020-01-11 17:29:56.796  INFO 10532 --- [           main] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test: [DefaultTestContext@3a393455 testClass = ApplicationTests, testInstance = com.example.soq59695741.ApplicationTests@5829e4f4, testMethod = test@ApplicationTests, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@13518f37 testClass = ApplicationTests, locations = '{}', classes = '{class com.example.soq59695741.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7fd7a283, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@16612a51, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@47c81abf, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@6b0d80ed], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.154 s - in com.example.soq59695741.ApplicationTests
2020-01-11 17:29:56.859  INFO 10532 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-01-11 17:29:56.859  INFO 10532 --- [extShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'
2020-01-11 17:29:56.861 ERROR 10532 --- [extShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000478: Unsuccessful: drop table a if exists
2020-01-11 17:29:56.870  INFO 10532 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2020-01-11 17:29:56.874  INFO 10532 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Results:

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 7.976 s