Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.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
Java Hibernate、Spring、PostgreSQL-列索引超出范围_Java_Postgresql_Hibernate_Spring Data Jpa - Fatal编程技术网

Java Hibernate、Spring、PostgreSQL-列索引超出范围

Java Hibernate、Spring、PostgreSQL-列索引超出范围,java,postgresql,hibernate,spring-data-jpa,Java,Postgresql,Hibernate,Spring Data Jpa,我无法将简单的数据结构持久化到数据库中 每条消息可以有多个消息接收器。我所需要的一切就是保存在数据库Message和MessageReceivers(MR)中。MR具有名为fk_message_id的列,该列应自动填充message_id(M) 在数据库(PostgreSQL)中,使用SQL代码创建表: CREATE TABLE public.message ( message_id integer NOT NULL DEFAULT nextval('message_message_id_se

我无法将简单的数据结构持久化到数据库中

每条消息可以有多个消息接收器。我所需要的一切就是保存在数据库Message和MessageReceivers(MR)中。MR具有名为fk_message_id的列,该列应自动填充message_id(M)

在数据库(PostgreSQL)中,使用SQL代码创建表:

CREATE TABLE public.message
(
 message_id integer NOT NULL DEFAULT nextval('message_message_id_seq'::regclass),
 fk_author_id integer NOT NULL,
 topic text NOT NULL,
 text text NOT NULL,
 audit_cd timestamp without time zone NOT NULL DEFAULT now(),
 audit_md timestamp without time zone,
 CONSTRAINT message_pkey PRIMARY KEY (message_id)
)

CREATE TABLE public.message_receiver
(
 fk_message_id integer NOT NULL,
 fk_user_id integer NOT NULL,
 is_read boolean NOT NULL,
 read_date timestamp without time zone,
 audit_cd timestamp without time zone NOT NULL DEFAULT now(),
 autid_md timestamp without time zone,
 CONSTRAINT message_receiver_pkey PRIMARY KEY (fk_message_id, fk_user_id),
 CONSTRAINT message_receiver_fk_message_id_fkey FOREIGN KEY (fk_message_id)
  REFERENCES public.message (message_id) MATCH SIMPLE
  ON UPDATE CASCADE ON DELETE CASCADE
)
Message.java

@Entity
@Table(name="message")
public class Message implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="message_message_id_seq")
@SequenceGenerator(name="message_message_id_seq", sequenceName="message_message_id_seq", allocationSize=1)
@Column(name="message_id")
private Long id;

@NotNull
@Column(name="fk_author_id")
private Long author;

@OneToMany
@Cascade(CascadeType.PERSIST)
@JoinColumn(name="fk_message_id", nullable = false)
private List<MessageReceiver> receivers;

@NotNull
@Column(name="topic")
private String topic;

@NotNull
@Column(name="text")
private String text;

@NotNull
@Column(name="audit_cd")
@Convert(converter=PersistentLocalDateTime.class)
private LocalDateTime sendDate;

...getters, setters, constructors...
}
@Entity
@Table(name="message_receiver")
public class MessageReceiver implements Serializable {

private static final long serialVersionUID = 2L;

@Id
@Column(name="fk_message_id")
private Long messageId;

@Id
@Column(name="fk_user_id")
private Long receiverId;

@NotNull
@Column(name="is_read")
private Boolean isRead;

@Column(name="read_date")
@Convert(converter = PersistentLocalDateTime.class)
private LocalDateTime readDate;

...getters, setters, constructors...
}
当我尝试使用接收者保存邮件时,我得到:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not insert: [com.example.foldermessage.model.MessageReceiver]; SQL [insert into message_receiver (is_read, read_date, fk_message_id, fk_user_id) values (?, ?, ?, ?)]; nested exception is org.hibernate.exception.DataException: could not insert: [com.example.foldermessage.model.MessageReceiver]] with root cause

org.postgresql.util.PSQLException: The column index is out of range: 5, number of columns: 4.
at org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:68) ~[postgresql-9.4.1211.jar:9.4.1211]
at org.postgresql.core.v3.SimpleParameterList.setNull(SimpleParameterList.java:157) ~[postgresql-9.4.1211.jar:9.4.1211]
at org.postgresql.jdbc.PgPreparedStatement.setNull(PgPreparedStatement.java:287) ~[postgresql-9.4.1211.jar:9.4.1211]
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:61) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:257) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:252) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:343) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrateId(AbstractEntityPersister.java:2636) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2604) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2883) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3386) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:560) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:434) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
我使用JpaRepository执行保存操作:

@Repository
public interface MessageRepository extends JpaRepository<Message, Long> {}
@存储库
公共接口MessageRepository扩展了JpaRepository{}
插入查询似乎还可以,但我看不出有任何错误


我还尝试将MR实体ID更改为带有@IdClass注释和@PrimaryKeyJoinColumn的复合键。那些尝试都没有帮助。

我找到了临时解决办法

  • 首先,我启用了DDL
    spring.jpa.hibernate.DDL auto=create(或update)
    来自动生成模式

  • 在上一个解决方案中,消息接收器具有主键
    fk\u消息\u id,fk\u用户\u id
    。此复合密钥的主要目的是防止向一个用户发送同一消息两次或多次

  • 我决定将生成的值替换为复合键。消息唯一性约束可以通过在PostgreSQL级别添加唯一性约束来实现

    MessageReceiver.java

    @Entity
    @Table(name="message_receiver")
    public class MessageReceiver implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @Column(name="message_receiver_id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="message_receiver_id_seq")
    @SequenceGenerator(name="message_receiver_id_seq", sequenceName="message_receiver_id_seq", allocationSize=1)
    private Long messageReceiverId;
    
    @NotNull
    @Column(name="fk_message_id")
    private Long messageId;
    
    @NotNull
    @Column(name="fk_user_id")
    private Long receiverId;
    
    @NotNull
    @Column(name="is_read")
    private Boolean isRead;
    
    @Column(name="read_date")
    @Convert(converter = PersistentLocalDateTime.class)
    private LocalDateTime readDate;
    
    ..getters, setters..
    
    Message.java

    @Entity
    @Table(name="message")
    public class Message implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="message_message_id_seq")
    @SequenceGenerator(name="message_message_id_seq", sequenceName="message_message_id_seq", allocationSize=1)
    @Column(name="message_id")
    private Long id;
    
    @NotNull
    @Column(name="fk_author_id")
    private Long author;
    
    @OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    @JoinColumn(name="fk_message_id")
    private List<MessageReceiver> receivers = new ArrayList<>();
    
    @NotNull
    @Column(name="topic")
    private String topic;
    
    @NotNull
    @Column(name="text")
    private String text;
    
    @NotNull
    @Column(name="audit_cd")
    @Convert(converter=PersistentLocalDateTime.class)
    private LocalDateTime sendDate;
    
    ..getters, setters..
    
    @实体
    @表(name=“message”)
    公共类消息实现可序列化{
    私有静态最终长serialVersionUID=1L;
    @身份证
    @GeneratedValue(策略=GenerationType.SEQUENCE,generator=“message\u message\u id\u seq”)
    @SequenceGenerator(name=“message\u message\u id\u seq”,sequenceName=“message\u message\u id\u seq”,allocationSize=1)
    @列(name=“message\u id”)
    私人长id;
    @NotNull
    @列(name=“fk\u author\u id”)
    私人长作者;
    @OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE})
    @JoinColumn(name=“fk\u message\u id”)
    私有列表接收者=新的ArrayList();
    @NotNull
    @列(name=“topic”)
    私有字符串主题;
    @NotNull
    @列(name=“text”)
    私有字符串文本;
    @NotNull
    @列(name=“audit\u cd”)
    @Convert(converter=PersistentLocalDateTime.class)
    私有LocalDateTime sendDate;
    …能手,二传手。。
    
    现在,我很好奇为什么第一个解决方案不起作用以及如何使它起作用。我尝试了@PrimaryKeyJoinColumn、@IdClass、@OneToMany(mappedBy)、@JoinColumn(可空、可插入、可更新)的混合

    当我启用DDL(创建)时,Hibernate将生成与我在开始时放置的相同的表。这意味着表结构不正确不会有问题

    如果更改生成主键的策略有帮助,那么保存复合键可能会导致错误。在日志中,我经常看到Hibernate添加到实体
    *\u IdBackref
    。可能它尝试将此id保存/映射到数据库中,但其列尚未准备好


    如果找到最终解决方案,我将发布。

    您的表中没有一个只有4列。您确定您的数据库架构与您的类结构匹配吗?(上次执行创建数据库的脚本是什么时候?)@我在文章开头提出的MikeNakis sql查询是直接从PgAdmin复制的。类结构必须与数据库表结构相同吗?在类中,我没有提出audit_md列。是的,类结构和数据库架构必须匹配,否则hibernate将尝试访问这些列数据库中不存在。请查找hibernate的
    hbm2ddl
    属性,该属性允许您从类结构自动创建数据库架构。如果您不想(或不能)要做到这一点,您还可以使用
    hbm2ddl
    至少让hibernate在程序启动期间验证您的类结构是否与数据库架构一致,以避免令人不快的意外情况。@MikeNakis我在java类中添加了缺少的列。现在我得到了相同的错误,但数字不同。查询:
    插入到消息接收器中(审核cd、is读取、autid md、读取日期、fk消息id、fk用户id)值(?,,,,,?,?)
    错误:
    org.postgresql.util.psqleexception:列索引超出范围:7,列数:6。
    好的,那么很明显,实际的postgres表不包含列
    audit\u cd,is\u read,autid\u md,read\u date,fk\u message\u id,fk\u user\u id
    。让它包含这些列。