Spring CrudRepository无法在复合主键中共享生成的id

时间:2017-09-16 17:27:03

标签: java spring spring-data-jpa composite-primary-key spring-repositories

我正在尝试使用 spring CRUDRepository 使用JPA数据库模型将新对象插入数据库( User.java UserInfo.java ) 。数据库模型与复合主键( UserPK.java )相关,其中一个是自动生成的(字段名为 id ),第二个(字段名为 type < / strong>)在开头设置。

使用 CRUDRepository UserRepository.java )创建新对象时出错 - 无法将新对象插入第二个模型( UserInfo.java < / strong>),因为 id 为null(正确添加了第一个模型)。我认为问题在于在数据库模型中共享/映射复合主键。 我用 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;
    /* ... */
}

spring CRUDRepository UserRepository.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);
}

使用 EntityManager 的存储库: UserRepositoryEM.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;
    }
}

1 个答案:

答案 0 :(得分:0)

name = input(...) if name in student: del student[name] else: print("Invalid name") User类需要稍加修改。主键的字段到列映射应位于UserPK类中。以下是更改,

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;
    }
}