我在將簡單數據結構存入數據庫時遇到了問題。Hibernate,Spring,PostgreSQL - 列索引超出範圍
每條消息可能有多個消息接收者。我需要的一切就是保存在數據庫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...
}
MessageReceiver.java
@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> {}
插入查詢似乎確定,我看不到任何錯誤了。
我也嘗試將MR實體ID更改爲具有@IdClass批註和@PrimaryKeyJoinColumn的複合鍵。那些嘗試沒有幫助。
您的表格只有4列。你確定你的數據庫模式與你的類結構相匹配嗎? (什麼時候是你最後一次執行創建你的數據庫的腳本?) –
@MikeNakis在帖子開頭的sql查詢是直接從PgAdmin複製的。 類結構是否必須與數據庫表結構相同?在類中我沒有放置audit_md列。 – mateusz
是的,類結構和數據庫模式必須匹配,否則預計hibernate會嘗試訪問數據庫中不存在的列。查看hibernate的'hbm2ddl'屬性,它允許你從你的類結構自動創建你的數據庫模式。如果你不想(或不能)這樣做,你也可以使用'hbm2ddl'來至少讓hibernate在程序啓動時驗證你的類結構是否與你的數據庫模式一致,以避免令人討厭的意外。 –