0

我試圖使用春天CRUDRepository使用JPA的數據庫模型中插入新的對象到數據庫(User.javaUserInfo.java)。數據庫模型與複合主鍵相關(UserPK.java),其中一個是自動生成的(字段名爲id),第二個(字段名爲類型)在開始時設置。春天CrudRepository無法股價生成的ID複合主鍵

而且我得到的錯誤,當我創建新的對象,使用CRUDRepositoryUserRepository.java) - 不能插入新的對象爲第二個模型(UserInfo.java),因爲ID爲空(第一種模式被正確添加)。我認爲問題在於共享/映射數據庫模型中的複合主鍵。 我嘗試了與EntityManager相同的模型,它不是錯誤 - 所有被添加。接下來我用@PrimaryKeyJoinColumns註釋,但是與上面的結果相同(但我不確定我是否正確使用它) - CRUDRepository失敗,並且EntityManager成功。

任何人都可以幫我找到解決辦法嗎?如果有人想運行代碼,我還會在GitHub上添加源代碼。

日誌如下:

登錄以下CRUDRepository

Hibernate: select user0_.id as id1_0_1_, user0_.type as type2_0_1_, user0_.email as email3_0_1_, user0_.login as login4_0_1_, userinfo1_.id as id3_1_0_, userinfo1_.type as type4_1_0_, userinfo1_.name as name1_1_0_, userinfo1_.surname as surname2_1_0_ from user user0_ left outer join user_info userinfo1_ on user0_.id=userinfo1_.id and user0_.type=userinfo1_.type where user0_.id=? and user0_.type=? 
Hibernate: call next value for seq_id 
Hibernate: select userinfo0_.id as id3_1_0_, userinfo0_.type as type4_1_0_, userinfo0_.name as name1_1_0_, userinfo0_.surname as surname2_1_0_ from user_info userinfo0_ where userinfo0_.id=? and userinfo0_.type=? 
Hibernate: insert into user (email, login, id, type) values (?, ?, ?, ?) 
Hibernate: insert into user_info (name, surname, id, type) values (?, ?, ?, ?) 
WARN 17653 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23502, SQLState: 23502 
ERROR 17653 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "ID"; SQL statement: 
insert into user_info (name, surname, id, type) values (?, ?, ?, ?) [23502-196] 
... 

登錄的EntityManager

Hibernate: call next value for seq_id 
Hibernate: insert into user (email, login, id, type) values (?, ?, ?, ?) 
Hibernate: insert into user_info (name, surname, id, type) values (?, ?, ?, ?) 

代碼:

主要模型:User.java

import com.fasterxml.jackson.annotation.JsonManagedReference; 
import javax.persistence.*; 
import javax.validation.constraints.NotNull; 
import java.io.Serializable; 

@Entity 
@Table(name = "USER") 
@IdClass(UserPK.class) 
public class User implements Serializable { 

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "user") 
    @JsonManagedReference 
    private UserInfo info; 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ID") 
    @SequenceGenerator(name = "SEQ_ID", sequenceName = "SEQ_ID", allocationSize = 1) 
    @NotNull 
    @Column(name = "ID") 
    private Long id; 
    @Id 
    @NotNull 
    @Column(name = "TYPE") 
    private String type; 
    @NotNull 
    @Column(name = "LOGIN") 
    private String login; 
    @NotNull 
    @Column(name = "EMAIL") 
    private String email; 
    /* ... */ 
} 

第二模型:UserInfo.java

import com.fasterxml.jackson.annotation.JsonBackReference; 
import javax.persistence.*; 
import java.io.Serializable; 

@Entity 
@Table(name = "USER_INFO") 
public class UserInfo implements Serializable { 

    @Id 
    @OneToOne(cascade = CascadeType.ALL) 
    @JoinColumns({ 
    @JoinColumn(name = "id", referencedColumnName = "id"), 
    @JoinColumn(name = "type", referencedColumnName = "type") 
    }) 
    @JsonBackReference 
    @MapsId 
    private User user; 

    @Column(name = "NAME") 
    private String name; 
    @Column(name = "SURNAME") 
    private String surname; 
    /* ... */ 
} 

組成主鍵:UserPK.java

import java.io.Serializable; 

public class UserPK implements Serializable { 
    private Long id; 
    private String type; 
    /* ... */ 
} 

彈簧CRUDRepositoryUserRepository.java

import org.springframework.data.repository.CrudRepository; 
import org.springframework.stereotype.Repository; 

@Repository 
public interface UserRepository extends CrudRepository<User, UserPK> { 
    User findByIdAndAndType(Long id, String type); 
} 

庫使用的EntityManagerUserRepositoryEM。java的

import org.springframework.stereotype.Repository; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.transaction.Transactional; 

@Repository 
@Transactional 
public class UserRepositoryEM { 

    @PersistenceContext 
    private EntityManager entityManager; 

    public User findByKey(UserPK key) { 
     return entityManager.find(User.class, key); 
    } 

    public User save(User user) { 
     entityManager.persist(user); 
     entityManager.flush(); 
     return user; 
    } 
} 

回答

0

UserUserPK類需要稍加修改。您的字段到主鍵的列映射應位於UserPK類中。這裏有變化,

@Entity 
@Table(name = "USER") 
public class User implements Serializable { 

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "user") 
    @JsonManagedReference 
    private UserInfo info; 

    @EmbeddedId 
    private UserPK id; 

    @Column(name = "LOGIN", nullable = false) 
    private String login; 

    @Column(name = "EMAIL", nullable = false) 
    private String email; 
    /* ... */ 

    @Embeddable 
    @SequenceGenerator(name = "SEQ_ID", initialValue=1, allocationSize=100) 
    public static class UserPK implements Serializable { 

     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ID") 
     @Column(name = "ID", nullable = false) 
     private Long id; 

     @Column(name = "TYPE", nullable = false) 
     private String type; 
    } 
} 

相應的改動庫,

@Repository 
public interface UserRepository extends CrudRepository<User, User.UserPK> { 
    User findByIdAndAndType(Long id, String type); 
} 
+0

感謝響應,我更改代碼,你說:** ** UserPK.java,** ** User.java + ** UserRepository.java **。您可以在[GitHub](https://github.com/kaczla/SpringBootCompositePrimaryKey/tree/embeddedid)上查看更改。現在是其他問題,無法生成密鑰 - 即使我設置了密鑰,也無法共享到** UserInfo.java ** – kaczla

+0

對UserPK類的wrt序列生成器做了一些修改。現在就試試。 –

+0

我更改** UserPK.java **,但它沒有幫助。查看日誌,hibernate沒有爲** UserPK.java **創建序列器,所以自動生成的id不能用@Embeddable註釋或者我們做錯了。 另一方面,我解決了共享/映射覆合主鍵的問題 - 我只是在** UserInfo.java **中添加了* @ EmbeddedId *註釋。當然你可以看到[GitHub](https://github.com/kaczla/SpringBootCompositePrimaryKey/tree/embeddedid) – kaczla