I am new to the hibernate world and I am getting the following error message when trying to execute a query with hibernate and postgres.
org.postgresql.util.PSQLException: ERROR: operator does not exist: text = bytea
Hint: No operator matches the given name and argument type(s). You might
need to add explicit type casts.
Here is my hibernate mapping (car.hbm.xml):
<hibernate-mapping>
<class name="Car" table="car"
schema="someSchema">
<id name="id" type="int" column="car_id">
<generator class="sequence">
<param name="sequence">car_seq</param>
</generator>
</id>
<property name="carMake">
<column name="car_make" sql-type="string"/>
</property>
<property name="carModel">
<column name="car_model" sql-type="string"/>
</property>
<property name="carVin" >
<column name="car_vin" sql-type="int" />
</property>
<property name="datePurchased">
<column name="date_purchased" sql-type="date"/>
</property>
<property name="retiredModel">
<column name="retired_model" sql-type="boolean"/>
</property>
</class>
On Postgres, here is what my table looks like:
CREATE TABLE car (
car_vin INTEGER NOT NULL DEFAULT nextval('car_seq'::regclass) PRIMARY KEY,
car_make TEXT NOT NULL,
car_model TEXT DEFAULT NULL,
date_purchased DATE DEFAULT now() NOT NULL,
retired_model BOOLEAN DEFAULT FALSE NOT NULL
);
Here is my model class (Car.java):
public class Car {
private int id;
private String carMake;
private String carModel;
private int carVin;
private Date datePurchased;
private boolean retiredModel;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCarModel() {
return carModel;
}
public void setcarModel(String carModel) {
this.carModel = carModel;
}
public String getcarMake() {
return carMake;
}
public void setcarMake(String carMake) {
this.carMake = carMake;
}
public Date getDatePurchased() {
return datePurchased;
}
public void setDatePurchased(Date datePurchased) {
this.datePurchased = datePurchased;
}
public boolean isRetired() {
return retiredModel;
}
public void setRetired(boolean retiredModel) {
this.retiredModel = retiredModel;
}
In my DAO layer, I am using the following line to query:
Query query = getSession().createQuery("from Car as c where " +
"c.carModel = ? AND c.carMake = ?").setParameter(0, carModel).setParameter(1, carMake);
carMake and carModel are both String datatypes passed on as method parameters in the DAO method.
Note that the strings in my hbm are mapped to TEXT in postgres, so I am guessing if that is the problem or not. If it is, how do I solve it ?
Я новичок в мире спящего режима и получаю следующее сообщение об ошибке при попытке выполнить запрос с помощью спящего режима и postgres.
org.postgresql.util.PSQLException: ERROR: operator does not exist: text = bytea
Hint: No operator matches the given name and argument type(s). You might
need to add explicit type casts.
Вот мое сопоставление спящего режима (car.hbm.xml):
<hibernate-mapping>
<class name="Car" table="car"
schema="someSchema">
<id name="id" type="int" column="car_id">
<generator class="sequence">
<param name="sequence">car_seq</param>
</generator>
</id>
<property name="carMake">
<column name="car_make" sql-type="string"/>
</property>
<property name="carModel">
<column name="car_model" sql-type="string"/>
</property>
<property name="carVin" >
<column name="car_vin" sql-type="int" />
</property>
<property name="datePurchased">
<column name="date_purchased" sql-type="date"/>
</property>
<property name="retiredModel">
<column name="retired_model" sql-type="boolean"/>
</property>
</class>
В Postgres вот как выглядит мой стол:
CREATE TABLE car (
car_vin INTEGER NOT NULL DEFAULT nextval('car_seq'::regclass) PRIMARY KEY,
car_make TEXT NOT NULL,
car_model TEXT DEFAULT NULL,
date_purchased DATE DEFAULT now() NOT NULL,
retired_model BOOLEAN DEFAULT FALSE NOT NULL
);
Вот мой модельный класс (Car.java):
public class Car {
private int id;
private String carMake;
private String carModel;
private int carVin;
private Date datePurchased;
private boolean retiredModel;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCarModel() {
return carModel;
}
public void setcarModel(String carModel) {
this.carModel = carModel;
}
public String getcarMake() {
return carMake;
}
public void setcarMake(String carMake) {
this.carMake = carMake;
}
public Date getDatePurchased() {
return datePurchased;
}
public void setDatePurchased(Date datePurchased) {
this.datePurchased = datePurchased;
}
public boolean isRetired() {
return retiredModel;
}
public void setRetired(boolean retiredModel) {
this.retiredModel = retiredModel;
}
В моем слое DAO я использую следующую строку для запроса:
Query query = getSession().createQuery("from Car as c where " +
"c.carModel = ? AND c.carMake = ?").setParameter(0, carModel).setParameter(1, carMake);
carMake и carModel являются строковыми типами данных, передаваемыми как параметры метода в методе DAO.
Обратите внимание, что строки в моем hbm отображаются в TEXT в postgres, поэтому я предполагаю, что это проблема или нет. Если да, то как это решить?
I am new to the hibernate world and I am getting the following error message when trying to execute a query with hibernate and postgres.
org.postgresql.util.PSQLException: ERROR: operator does not exist: text = bytea
Hint: No operator matches the given name and argument type(s). You might
need to add explicit type casts.
Here is my hibernate mapping (car.hbm.xml):
<hibernate-mapping>
<class name="Car" table="car"
schema="someSchema">
<id name="id" type="int" column="car_id">
<generator class="sequence">
<param name="sequence">car_seq</param>
</generator>
</id>
<property name="carMake">
<column name="car_make" sql-type="string"/>
</property>
<property name="carModel">
<column name="car_model" sql-type="string"/>
</property>
<property name="carVin" >
<column name="car_vin" sql-type="int" />
</property>
<property name="datePurchased">
<column name="date_purchased" sql-type="date"/>
</property>
<property name="retiredModel">
<column name="retired_model" sql-type="boolean"/>
</property>
</class>
On Postgres, here is what my table looks like:
CREATE TABLE car (
car_vin INTEGER NOT NULL DEFAULT nextval('car_seq'::regclass) PRIMARY KEY,
car_make TEXT NOT NULL,
car_model TEXT DEFAULT NULL,
date_purchased DATE DEFAULT now() NOT NULL,
retired_model BOOLEAN DEFAULT FALSE NOT NULL
);
Here is my model class (Car.java):
public class Car {
private int id;
private String carMake;
private String carModel;
private int carVin;
private Date datePurchased;
private boolean retiredModel;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCarModel() {
return carModel;
}
public void setcarModel(String carModel) {
this.carModel = carModel;
}
public String getcarMake() {
return carMake;
}
public void setcarMake(String carMake) {
this.carMake = carMake;
}
public Date getDatePurchased() {
return datePurchased;
}
public void setDatePurchased(Date datePurchased) {
this.datePurchased = datePurchased;
}
public boolean isRetired() {
return retiredModel;
}
public void setRetired(boolean retiredModel) {
this.retiredModel = retiredModel;
}
In my DAO layer, I am using the following line to query:
Query query = getSession().createQuery("from Car as c where " +
"c.carModel = ? AND c.carMake = ?").setParameter(0, carModel).setParameter(1, carMake);
carMake and carModel are both String datatypes passed on as method parameters in the DAO method.
Note that the strings in my hbm are mapped to TEXT in postgres, so I am guessing if that is the problem or not. If it is, how do I solve it ?
It is weird but the query does not handle null very well. When I changed the query to:
Query query = getSession().createQuery("from Car as c where " +
"c.carModel = ? AND c.carMake is null").setParameter(0, carModel);
it works fine since the DAO needs to query the make as NULL. So if it is not null, I need to have two sets of query, one that is hardcoded to select null as above, other to setParam(1, carMake).
Weird but I think this works.
#java #postgresql #jpa
Вопрос:
Я пытаюсь сохранить файл Excel и сохранить его в своей базе данных. Я получаю эту ошибку:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
org.postgresql.util.PSQLException: ERROR: operator does not exist: character varying = bytea
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
Это мой метод отправки сообщений контроллера:
@PostMapping
public ResponseEntity<DocumentCreateResponse> addDocument(@RequestParam("file") MultipartFile file) throws IOException {
Path copyLocation = Paths.get(uploadDir, Objects.requireNonNull(file.getOriginalFilename()));
Files.copy(file.getInputStream(), copyLocation, StandardCopyOption.REPLACE_EXISTING);
Document savedDocument = documentService.save(copyLocation.toAbsolutePath().toFile());
if (savedDocument == null){
return new ResponseEntity<>(new DocumentCreateResponse(null), null, HttpStatus.NOT_ACCEPTABLE);
}
return new ResponseEntity<>(new DocumentCreateResponse(savedDocument.getId()), null, HttpStatus.ACCEPTED);
}
Это класс документов:
@Entity
public class DocumentEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name ="document_id")
private Long id;
@Column(name ="document_file")
private File file;
public DocumentEntity() {
}
public DocumentEntity(File file) {
this.file = file;
}
}
И это мой файл создания схемы (я использую Flyway и PostgreSQL)
create table if not exists document_entity
(
document_id bigserial
constraint document_entity_document_id
not null primary key,
document_file varchar not null
);
Где я должен добавить изменения, чтобы мои файлы сохранялись правильно и не вызывали эту ошибку? Я читал статьи и видел эту ошибку, но я не вижу, что я должен изменить в своем коде.
public class DocumentService implements DocumentServicePort {
private final DocumentRepository documentRepository;
public DocumentService(DocumentRepository documentRepository) {
this.documentRepository = documentRepository;
}
@Override
public Document save(File file) {
Document document = new Document(file);
if (document.hasValidExtension(document)) {
documentRepository.saveDocument(document);
return document;
}
return null;
}
}
Комментарии:
1. пожалуйста, добавьте также свой класс репозитория. в чем заключается реализация
documentService.save
2. Я добавляю класс DocumentService в post, documentRepository имеет только один метод сохранения документа(Документ-документ);
3. метод hasValidExtension проверяет , правильно ли расширение, если нет, он не возвращает документ
4. вы используете JPA для сохранения или запроса?
5. Я использую JPA .
Ответ №1:
Вы объявили свой файл как varchar в базе данных, где в вашем приложении вы объявили это поле как Файл.
Вы можете сделать несколько вещей, но для случая, о котором вы упомянули, измените тип столбца в базе данных. Это должно быть «bytea».
запустите это в бд (лучше, если таблица пуста):
ALTER TABLE document_entity ALTER COLUMN document_file TYPE bytea USING document_file::TEXT::BYTEA;
Комментарии:
1. Это не работает, все равно получается та же ошибка. Я даже удалил базу данных и настроил ее снова, но она не работала
2. да, это так, так что я понятия не имею, что происходит
3. вы проверили, был ли тип столбца обновлен до bytea?
4. используйте
@Lob
аннотацию к полю файла в классе сущностей и измените тип переменной наbyte[]
Контрольный список устранения неполадок:
# 1: В зависимости от типа используемой базы данных вы можете найти имена столбцов и их соответствующие типы данных с помощью этой команды SQL:
SELECT
table_name,
column_name,
data_type
FROM
information_schema.columns
WHERE
table_name = 'the-name-of-the-table-in-the-database';
Ожидаемые результаты дадут вам три столбца; и особенно столбец data_type.
Убедитесь, что ваш класс Pojo и соответствующие типы данных соответствуют друг другу.
Обратите внимание: bigint (тип данных) в таблице внутри базы данных может легко совпадать с Long. целое с внутр. символ, варьирующийся в зависимости от строки или основного класса Java, например. класс, хранящий Enums, и так далее.
После подтверждения вышеизложенного выполните следующую проверку -> устранение неполадок:
# 2 : Основная проверка при устранении неполадок заключается в том, чтобы убедиться, что все типы данных полностью совпадают. И обратите внимание на параметры, передаваемые в запрос.
Передача перечисления или любого другого типа данных или типа перечисления, не соответствующего типам данных SQL, может вызвать ошибку (ошибки) «не сопоставлена», даже если класс pojo идеально соответствует структуре таблицы в базе данных.
пример pojo: UserAccountBalance.class
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
@Builder//Lombok
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Data//Lombok
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Schema
@Entity(name = "user_account_balance")
@Table(name = "user_account_balance")
public class UserAccountBalance {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private long id;
@NotNull
@Column(name = "username", nullable = false)
private String userName;
@NotNull
@Column(name="currency_code", nullable = false)
@Enumerated(EnumType.STRING)
private CurrencyCode currencyCode;
@NotNull
@Column(name = "balance", nullable = false)
private BigDecimal balance;
//Could be placed into and AuditModel class
@Column(name = "datecreated", nullable = false, updatable = false)
@JsonIgnore
@DateCreated
@CreationTimestamp
private LocalDateTime dateCreated;
@Column(name = "date_updated", nullable = false, updatable = false)
@JsonIgnore
@DateUpdated
private LocalDateTime dateUpdated;
@NotNull
@Column(name = "active")
@JsonIgnore
private int active;
@Column(name = "deleted")
@JsonIgnore
private int deleted;
}
Класс репозитория:
//Вариант 1: UserAccountBalanceRepository.class
@Repository
public abstract class UserAccountBalanceRepository implements CrudRepository<UserAccountBalance, Long> {
private final EntityManager entityManager;
public UserAccountBalanceRepository(@CurrentSession EntityManager entityManager){
this.entityManager = entityManager;
}
@Transactional(readOnly = true)
@Query(
value="SELECT uab.*" +
" FROM public.user_account_balance uab" +
" WHERE (currency_code =cast(:currencyCode AS text)" +
" AND userName =:userName" +
" AND active =:active)",
countQuery = "SELECT uab.*" +
" FROM public.user_account_balance uab" +
" WHERE (currency_code = cast(:currencyCode AS text)" +
" AND userName =:userName" +
" AND active =:active)",
nativeQuery = true
)
public abstract Optional<UserAccountBalance> findByUserAccountBalance_UserName_And_CurrencyCode(
String userName,
CurrencyCode currencyCode,
int active
);
}
//Вариант 2: UserAccountBalanceRepository.class
@Repository
public abstract class UserAccountBalanceRepository implements CrudRepository<UserAccountBalance, Long> {
private final EntityManager entityManager;
public UserAccountBalanceRepository(@CurrentSession EntityManager entityManager){
this.entityManager = entityManager;
}
@Transactional(readOnly = true)
@Query(
value="SELECT uab.*" +
" FROM public.user_account_balance uab" +
" WHERE (currency_code =:currencyCode" +
" AND userName =:userName" +
" AND active =:active)",
countQuery = "SELECT uab.*" +
" FROM public.user_account_balance uab" +
" WHERE (currency_code = :currencyCode" +
" AND userName =:userName" +
" AND active =:active)",
nativeQuery = true
)
public abstract Optional<UserAccountBalance> findByUserAccountBalance_UserName_And_CurrencyCode(
String userName,
String currencyCode,/*this is what truly worked out for me perfectly*/
int active
);
}
№3. Тестировать и еще раз тестировать. Если проблема не устранена, наберитесь терпения и еще раз просмотрите все свои переменные и классы.
№ 4. Если устранение неполадок с использованием варианта № 3 по-прежнему не помогает, подумайте о небольшой прогулке, небольшом отдыхе и свежим взглядом, чтобы посмотреть на все заново, начиная с устранения неполадок № 1.
Надеюсь, это поможет. Здоровья и мира.