ОШИБКА: столбец publish_date имеет тип date, но выражение имеет тип bytea

Я пытаюсь вставить объекты типа Book в базу данных, и один из столбцов указан как дата, но в соответствии с этим исключением:

Caused by: org.postgresql.util.PSQLException: ERROR: column "publish_date" is of type date but expression is of type bytea
  Hint: You will need to rewrite or cast the expression.
  Position: 94
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2412)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2125)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:297)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
    ... 11 more

помещается как bytea. Я не уверен, почему это так, потому что в базе данных сам столбец имеет тип date, а столбец в моем классе Book имеет тип date. Я могу показать код ниже:

package examples.pubhub.model;

import java.time.LocalDate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="books")
public class Book {

    @Id
    @Column(name="isbn_13")
    public String isbn_13;  // International Standard Book Number, unique

    @Column(name="title")
    private String title;

    @Column(name="author")
    private String author;

    @Column(name="publish_date")
    private LocalDate publish_date; // Date of publish to the website

    @Column(name="price")
    private double price;

    @Column(name="content")
    private byte[] content;

    // Constructor used when no date is specified
    public Book(String isbn, String title, String author, byte[] content, double price) {
        super();
        this.isbn_13 = isbn;
        this.title = title;
        this.author = author;
        this.publish_date = LocalDate.now();
        this.content = content;
        this.price = price;
    }

    // Constructor used when a date is specified
    public Book(String isbn, String title, String author, LocalDate publishDate, double price, byte[] content) {
        super();
        this.isbn_13 = isbn;
        this.title = title;
        this.author = author;
        this.publish_date = publishDate;
        this.content = content;
        this.price = price;
    }

    // Default constructor
    public Book() {

    }

    public String getIsbn_13() {
        return isbn_13;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public LocalDate getPublish_date() {
        return publish_date;
    }


    public void setPublish_date(LocalDate publishDate) {
        this.publish_date = publishDate;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public byte[] getContent() {
        return content;
    }

    public void setContent(byte[] content) {
        this.content = content;
    }

    public void setIsbn_13(String isbn) {
        this.isbn_13 = isbn;

    }

}

И это автономный класс, который я тестирую:

package examples.pubhub.utilities;

import java.time.LocalDate;


import examples.pubhub.dao.BookDAO;
import examples.pubhub.dao.BooktagDAO;
import examples.pubhub.model.Book;
import examples.pubhub.model.Booktag;

public class PublishBookTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String isbn = "1234123412341";
        String title = "Title";
        String author = "Haisam";
        String book_tag = "Science Fiction";


        BookDAO database = DAOUtilities.getBookDAO();
        Book tempBook = database.getBookByISBN(isbn);
        BooktagDAO tagdao = DAOUtilities.getBooktagDAO();
        Booktag tempBooktag = tagdao.getBookTagByISBN(isbn);

        if (tempBook != null && tempBooktag != null) {
            // ASSERT: book with isbn already exists

            System.out.println("ISBN already exists.");


        } else {

            Book book = new Book();
            Booktag booktag = new Booktag();
            book.setIsbn_13(isbn);
            book.setTitle(title);
            book.setAuthor(author);
            book.setPrice(124);
            book.setPublish_date(LocalDate.now());
            book.setContent(null);
            booktag.setBook_tag(book_tag);
            booktag.setBook_isbn(isbn);
            booktag.setBook_title(title);


            boolean isSuccess_booktag = tagdao.addTag(booktag);
            boolean isSuccess_book = database.addBook(book);



        if (isSuccess_book && isSuccess_booktag) {

            System.out.println("Added.");

        } else {

            System.out.println("Not added.");
        }


            }
        }

    }

Если кто-нибудь знает, как конвертировать из bytea на сегодняшний день, или в чем может быть суть этой проблемы, я буду вечно благодарен. Спасибо за уделенное время.

TL; DR: транзакция не фиксируется из-за несовместимости ввода между LocalDate publish_date и фактическим столбцом publish_date в базе данных, который имеет тип date. Не знаю почему.


person Haisam Tarek Elkewidy    schedule 12.07.2017    source источник


Ответы (1)


Создайте LocalDateToWhateverDBTypeConverter. Вот как это сделать.

Изменить:

Есть два варианта определения использования конвертера. Первый - установить autoapply=true в аннотации @Converter класса Converter. В этом случае поставщик JPA будет использовать этот Converter для преобразования всех атрибутов сущности данного типа. Если autoapply установлен в false, вам нужно добавить аннотацию javax.persistence.Convert ко всем атрибутам, которые должны быть преобразованы, и указать класс Converter. В следующем фрагменте кода показан пример этого подхода:

@Entity
public class RectangleEntity
{

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;

   @Column
   private Integer x;

   @Column
   private Integer y;

   @Column
   @Convert(converter = ColorConverter.class)
   private Color color;

   ...
}
person Abhijit Sarkar    schedule 12.07.2017
comment
Мог бы я просто вызвать класс для преобразования из LocalDate в Date в методе book.setPublish_date ()? - person Haisam Tarek Elkewidy; 12.07.2017
comment
@HaisamTarekElkewidy В предоставленной мной ссылке есть инструкции, начинающиеся в строке 40; вы хотите, чтобы я прочитал их для вас? - person Abhijit Sarkar; 12.07.2017
comment
Я могу прочитать инструкции, сэр. Я не использую Spring в этом проекте, поэтому, судя по всему, мне нужно будет искать банки, упомянутые в классе. Я сделаю все возможное, чтобы это сработало. - person Haisam Tarek Elkewidy; 12.07.2017
comment
Итак, если я правильно это понимаю, я создаю класс, который преобразует LocalDate в настоящее время, а затем в переменной publish_date для книги я аннотирую его так? Преобразование столбца (преобразователь = LocalDatetoDate.class), если LocalDatetoDate было именем класса? - person Haisam Tarek Elkewidy; 12.07.2017
comment
В них используются jar-файлы springframework, поэтому мне нужно их добавить. Ладно, тогда я постараюсь, чтобы это сработало. - person Haisam Tarek Elkewidy; 12.07.2017
comment
В приведенном мной примере могут использоваться банки Spring (я не проверял), но вы можете найти миллион других примеров, если вы Google для конвертера JPA, которые не имеют ничего общего со Spring. Вам нужно прочитать JPA, прежде чем начинать писать код. - person Abhijit Sarkar; 12.07.2017
comment
В итоге я использовал уже встроенный метод java.sql.Date.valueOf (LocalDate) для преобразования, и теперь он работает. Но вы привели меня к этому, поэтому я считаю это приемлемым ответом. - person Haisam Tarek Elkewidy; 12.07.2017
comment
По сути, любой, кто это читает, должен заметить, что, вероятно, лучше преобразовать LocalDate.now () в тип Date для взаимодействия с базой данных, потому что иногда он будет идентифицироваться как байт. - person Haisam Tarek Elkewidy; 12.07.2017
comment
@HaisamTarekElkewidy, который зависит от того, как дата хранится в БД. Рекомендуется хранить как Instant, а не Date. - person Abhijit Sarkar; 12.07.2017
comment
Есть ли лучший способ сделать это сейчас? - person Saurabh Shrivastava; 09.07.2019