Spring Data Native Query uses VARBINARY for null String #Param - spring-data-jpa

I have a JpaRepository, with a native query in it:
#Query (value = "SELECT t.team_name FROM teams t " +
"WHERE (:teamcode IS NULL OR t.team_code = :teamcode) ",
nativeQuery = true)
List<Object[]> getTeamNames(#Param("teamcode") #Nullable String teamCode);
If I pass a non-null value, it works fine - the binding parameter type is VARCHAR. However, if I pass in a null parameter value, then the binding type is VARBINARY, and the query fails with the error:
SQL Error: 0, SQLState: 42883
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.
Table:
CREATE TABLE teams (
team_id BIGINT NOT NULL,
team_code VARCHAR(24) NOT NULL,
team_name VARCHAR(200),
team_desc VARCHAR(2000),
)
Entity:
#Entity
#DynamicUpdate
#Getter
#Setter
#EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
#Table(name = "teams", schema = "public")
public class Team extends BaseEntity
{
#Id
#Column(name = "team_id", nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ent_generator")
#SequenceGenerator(name = "ent_generator", sequenceName = "entity_seq", allocationSize = 1)
private long teamId;
#EqualsAndHashCode.Include
#Basic
#Column(name = "team_code", length = 24)
private String teamCode;
#Basic
#Column(name = "team_name", length = 200)
private String teamName;
#Basic
#Column(name = "team_desc", length = 2000)
private String teamDescription;
}
How do I resolve this?

Related

org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint, Id Colums not able generate by sequcece in Hibernat

I am getting an error that Id column is not able to generate.
which will have the Getters and Setters.
Note: In my case, Primary Key was bookingId.
"Id" has to be a sequence number.
Below is the save method.
At the time of save is was not able to generate value for the column.
Below is My Entity.
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Id
#Column(name = "booking_id")
private String bookingId;
#Column(name = "booked_by")
private String bookedBy;
#Column(name = "booking_status")
private int bookingStatus;
#Column(name = "booking_rcv")
private Date bookingRcv;
#Column(name = "chargeable_kgs")
private BigDecimal chargeableKgs;
}
Here we will have all the getters and setters, Constructors, hashcode, and equals methods.
#Transactional
#Override
public Booking saveBooking(Booking booking) {
Booking savedBooking = bookingRepository.save(booking);
if (savedBooking.getId() != null) {
booking.setId(savedBooking.getId());
}
booking.setVersion(savedBooking.getVersion());
bookingRepository.flush();
// bookingRepository.refresh(booking);
LOGGER.debug("savedbooking id::" + savedBooking.getId());
return savedBooking;
}
I am using postgre DB and Hibernate.

Spring JPaRepository not recognizing Column

I am working on a simple spring endpoint. My current db table sql is:
CREATE TABLE develop.usermetrics (
metricId SERIAL PRIMARY KEY,
uid varchar(12),
deptCode varchar(10),
orgGroup varchar(10),
orgUnit varchar(10),
orgCode varchar(10),
workLocationCode varchar(10),
campusId varchar(20),
userRole varchar(50),
metricDate timestamp
);
And my entity contains:
#Table(name = "usermetrics")
#Entity
public class UserMetricsEntity {
#Id
#Column(name = "metricId")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long metricId;
#Column(name = "uid")
private String uid;
#Column(name = "deptCode")
private String deptCode;
#Column(name = "orgGroup")
private String orgGroup;
#Column(name = "orgUnit")
private String orgUnit;
#Column(name = "orgCode")
private String orgCode;
#Column(name = "workLocationCode")
private String workLocationCode;
#Column(name = "campusId")
private String campusId;
#Column(name = "userRole")
private String userRole;
#Column(name = "metricDate")
private LocalDateTime metricDate;
When calling the save method of the repository I get the error:
UserMetricsEntity{metricId=null, uid='105735781', deptCode='Z05511', orgGroup='F&O', orgUnit='CIO', orgCode='0F', workLocationCode='MPG', campusId='GDLPLANT', userRole='Fullstack Developer', metricDate=2021-11-01T12:45:22.588191}
2021-11-01 12:45:23.029 WARN 57529 --- [nio-8082-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 42703
2021-11-01 12:45:23.029 ERROR 57529 --- [nio-8082-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: column "campus_id" of relation "usermetrics" does not exist
The first line of the log being a toString of the Entity.
Even though I named with camel case on the table creating sql, pgadmin changed the caps to lowercase. I changed the naming convention on the entity class to all lowercase and it worked.

NamedNativeQuery JPA null primary keys exception

I created a named query that looks like this with a result set mapping:
#NamedNativeQueries({ #NamedNativeQuery(name = "Q_INSTRUMENTS", query = "SELECT i.ID, i.TICKER, i.ISIN, i.SEDOL, i.NAME, i.COUNTRY_ID, i.CONTRACT_SIZE, i.EXPIRY_DATE, i.TYPE_ID FROM INSTRUMENT i INNER JOIN COUNTRY c ON i.COUNTRY_ID = c.ID"
+ " GROUP BY i.ID, i.TICKER, i.ISIN, i.SEDOL, i.COUNTRY_ID, i.CONTRACT_SIZE, i.EXPIRY_DATE, i.TYPE_ID, c.NAME HAVING i.ID = MAX(i.ID) ORDER BY i.NAME, c.NAME ASC", resultClass = Instrument.class, resultSetMapping = "InstrumentMapping") })
#SqlResultSetMapping(name = "InstrumentMapping", entities = { #EntityResult(entityClass = Instrument.class, fields = {
#FieldResult(name = "id", column = "ID"), #FieldResult(name = "ticker", column = "TICKER"),
#FieldResult(name = "sedol", column = "SEDOL"), #FieldResult(name = "isin", column = "ISIN"),
#FieldResult(name = "name", column = "NAME"), #FieldResult(name = "countryId", column = "COUNTRY_ID"),
#FieldResult(name = "contractSize", column = "CONTRACT_SIZE"),
#FieldResult(name = "expiryDate", column = "EXPIRY_DATE"), #FieldResult(name = "typeId", column = "TYPE_ID") }) })
and here is the class that is annotated with this named query
public class Instrument extends ManagedEntityBase{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(length = 10)
private String ticker;
#Column(length = 30)
private String isin;
#Column(length = 10, unique = true, nullable = false)
private String sedol;
#Column(length = 60, nullable = false)
private String name;
#Column(name = "COUNTRY_ID", nullable = false, insertable = false, updatable = false)
private long countryId;
#Column(name = "TYPE_ID", nullable = false, insertable = false, updatable = false)
private byte typeId;
#Column(name = "CONTRACT_SIZE", nullable = false)
private Long contractSize;
#Transient
private String contractSizeString;
#Temporal(TemporalType.DATE)
#Column(name = "EXPIRY_DATE")
private Date expiryDate;
public Instrument() {
// Default constructor
this.contractSize = 1L;
}
ublic Instrument(String sedol, Country country, InstrumentType type) {
this();
this.sedol = sedol;
this.country = country;
this.type = type;
}
/**
* Creates an {#link Instrument} with the given sedol, isin, country and type.
*
* #param sedol instrument sedol
* #param isin instrument isin
* #param country instrument country
* #param name
* #param ticker
* #param type instrument type
*/
public Instrument(String sedol, String isin, Country country, String name, String ticker, InstrumentType type) {
this(sedol, country, type);
this.isin = isin;
this.name = name;
this.ticker = ticker;
}
}
When I try to call the name query:
public static List<Instrument> getInstruments() {
return DatabaseUtility.getEntityManager().createNamedQuery("Q_INSTRUMENTS").getResultList();
}
I get the following error:
[EL Warning]: 2020-01-31 15:55:40.732--UnitOfWork(1788318093)--Exception [EclipseLink-6044] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.QueryException
Exception Description: The primary key read from the row [ArrayRecord(
=> 3000000002285
=> 00577
=> BMG8827A1045
=> BYX9N24
=> 13 HOLDINGS LTD, THE
=> 2
=> 1
=> null
=> 1)] during the execution of the query was detected to be null. Primary keys must not contain null.
Query: ReadAllQuery(name="Q_INSTRUMENTS" referenceClass=Instrument sql="SELECT i.ID, i.TICKER, i.ISIN, i.SEDOL, i.NAME, i.COUNTRY_ID, i.CONTRACT_SIZE, i.EXPIRY_DATE, i.TYPE_ID FROM INSTRUMENT i INNER JOIN COUNTRY c ON i.COUNTRY_ID = c.ID GROUP BY i.ID, i.TICKER, i.ISIN, i.SEDOL, i.COUNTRY_ID, i.CONTRACT_SIZE, i.EXPIRY_DATE, i.TYPE_ID, c.NAME HAVING i.ID = MAX(i.ID) ORDER BY i.NAME, c.NAME ASC")
In the table the expiry_date is indeed null but this does not take part from primary key and by default the nullable value is true for expiry date.
I use EclipseLink with PostreSQL.
I try to migrate the current code from old Sybase to new PostreSQL. With Sybase datasource the error does not happen.
I tried using
<property name="eclipselink.jpa.uppercase-column-names" value="true"/>
to make sure the mapping to the columns is not made wrong, but it didn't fix my issue
It seems that my question had its answer in it. The problem was due to wrong mapping for id. The mapping was done using "id" but the column in database is ID (capitalized). That's why I had null for id.
The solution was to put
<property name="eclipselink.jpa.uppercase-column-names" value="true"/>
in the right persistance-unit.

Postgres Bit Variant equivalent data type in Java

I Have a Postgres sql database with data in it. Im trying to insert data from my Spring-Data-JPA project with Hibernate mappings. I am getting
ERROR: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: column "is_active" is of type bit varying but expression is of type oid
Here is my entity
#Entity
#Table(schema = "shard_1", name = "pages")
#XmlRootElement
#NamedQueries({ #NamedQuery(name = "Pages.findAll", query = "SELECT p FROM Pages p"),
#NamedQuery(name = "Pages.findById", query = "SELECT p FROM Pages p WHERE p.id = :id"),
#NamedQuery(name = "Pages.findByPageNumber", query = "SELECT p FROM Pages p WHERE p.pageNumber = :pageNumber"),
#NamedQuery(name = "Pages.findByTitle", query = "SELECT p FROM Pages p WHERE p.title = :title"),
#NamedQuery(name = "Pages.findBySectionId", query = "SELECT p FROM Pages p WHERE p.sectionId = :sectionId"),
#NamedQuery(name = "Pages.findByVersionId", query = "SELECT p FROM Pages p WHERE p.versionId = :versionId"),
#NamedQuery(name = "Pages.findByCreated", query = "SELECT p FROM Pages p WHERE p.created = :created"),
#NamedQuery(name = "Pages.findByModified", query = "SELECT p FROM Pages p WHERE p.modified = :modified"),
#NamedQuery(name = "Pages.findByPdfcontent", query = "SELECT p FROM Pages p WHERE p.pdfcontent = :pdfcontent") })
public class Pages implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(nullable = false)
private Long id;
#Column(name = "page_number")
private Integer pageNumber;
#Column(length = 2147483647)
private String title;
#Column(name = "section_id")
private BigInteger sectionId;
#Column(name = "version_id")
private BigInteger versionId;
#Lob
#Column(name = "is_active")
private Object isActive;
#Temporal(TemporalType.TIMESTAMP)
private Date created;
#Temporal(TemporalType.TIMESTAMP)
private Date modified;
#Column(length = 2147483647)
private String pdfcontent;
}
This is my postgres table
CREATE TABLE shard_1.pages
(
id bigint NOT NULL DEFAULT shard_1.id_generator(),
page_number integer,
title text COLLATE pg_catalog."default",
section_id bigint,
version_id bigint,
is_active bit varying,
created timestamp without time zone,
modified timestamp without time zone,
pdfcontent text COLLATE pg_catalog."default",
CONSTRAINT pages_pkey PRIMARY KEY (id)
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
ALTER TABLE shard_1.pages
OWNER to root;
I tried Java datatypes boolean, string, char array, int, byte[] but fails with everything. What datatype for the field is_active should I use here?
Try to remove #Lob , i.e :
#Column(name = "is_active")
private Boolean isActive;
And alter your table 'shard_1.pages' just like this :
ALTER TABLE shard_1.pages DROP COLUMN is_active;
ALTER TABLE shard_1.pagese ADD COLUMN is_active boolean;

JPA2/EclipseLink OneToMany cascade persist issue "Referential integrity constraint violation"

I have two entities A and B:
A.java:
...
public class A implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "IDA", nullable = false)
private Integer ida;
#Basic(optional = false)
#Column(name = "NAME", nullable = false, length = 30)
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "a")
private List<B> bList=new ArrayList();
public void addB(B bp){
bp.setA(this);
bList.add(bp);
}
...
B.java:
...
public class B implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected BPK bPK;
#Basic(optional = false)
#Column(name = "NAME", nullable = false, length = 30)
private String name;
#JoinColumn(name = "A_IDA", referencedColumnName = "IDA", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private A a;
...
the bPK field is a Composite Primary Key:
#Embeddable
public class BPK implements Serializable {
#Basic(optional = false)
#Column(name = "IDB", nullable = false, length = 20)
private String idb;
#Basic(optional = false)
#Column(name = "A_IDA", nullable = false)
private int aIda;
public BPK() {
}
public BPK(String idb, int aIda) {
this.idb = idb;
this.aIda = aIda;
}
...
SQL code:
CREATE TABLE A (
idA INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
PRIMARY KEY(idA)
);
CREATE TABLE B (
idB VARCHAR(20) NOT NULL,
A_idA INTEGER UNSIGNED NOT NULL,
name VARCHAR(30) NOT NULL,
PRIMARY KEY(idB, A_idA),
FOREIGN KEY(A_idA)
REFERENCES A(idA)
ON DELETE NO ACTION
ON UPDATE NO ACTION
);
the main code:
A a=new A(null,"A1");
BPK bpk=new BPK();
bpk.setIdb("b1");
a.addB(new B(bpk,"B1"));
EntityManager em=getEntityManager();
em.getTransaction().begin();
em.persist(a);
em.getTransaction().commit();
I get this error:
Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
[EL Warning]: 2012-03-26 01:29:16.724--UnitOfWork(1902320872)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "CONSTRAINT_42_1: PUBLIC.B FOREIGN KEY(A_IDA) REFERENCES PUBLIC.A(IDA)"; SQL statement:
Internal Exception: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "CONSTRAINT_42_1: PUBLIC.B FOREIGN KEY(A_IDA) REFERENCES PUBLIC.A(IDA)";...
the error indicates a violation of integrity constrains, but why?
a single possibility whether the insertion of the entity B is made before A...
Any help please?
Thank you in advance.
EDIT:
solved just replace this :
#JoinColumn(name = "A_IDA", referencedColumnName = "IDA", nullable = false, insertable = false, updatable = false)
by this one:
#MapsId("aIda")
finally B.java:
#NamedQuery(name = "B.findByName", query = "SELECT b FROM B b WHERE b.name = :name")})
public class B implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected BPK bPK;
#Basic(optional = false)
#Column(name = "NAME", nullable = false, length = 30)
private String name;
#MapsId("aIda")
#ManyToOne(optional = false)
private A a;
You have the A_AID field controlled by the aIda attribute in the Embeddable - that means this attribute must be set with the value from A before you can persist B.
If you are using using JPA 2.0, you can mark the #ManyToOne with the #MapsId("aIda") which will allow you to remove the #JoinColumn for it. This will make the JPA provider set the value in b.bPK.aIda with the value from A on persist.
If you are not using JPA 2,0, you can either set it yourself by first persisting A and then changing your addB method to also set B's bPK.aIda, or you can change the fields so that the JoinColumn is writable and make the bPK.aIda insertable=false, updatable=false.