Spring Boot + PostgreSql Sequence not available - spring

I am working in a project developed with Spring Boot and PostgreSql as Database.
I have created a sequence user_seq in PostgreSql for my user table
CREATE SEQUENCE "USER_MGMT"."USER_SEQ"
INCREMENT 1
START 1000
MINVALUE 1000
MAXVALUE 99999999
CACHE 1;
ALTER SEQUENCE "USER_MGMT"."USER_SEQ"
OWNER TO postgres;
Here is my user Table
CREATE TABLE "USER_MGMT"."USER"
(
"USER_ID" bigint NOT NULL DEFAULT nextval('"USER_MGMT"."USER_SEQ"'::regclass),
"FIRST_NAME" character varying(30) COLLATE pg_catalog."default" NOT NULL,
"LAST_NAME" character varying(50) COLLATE pg_catalog."default" NOT NULL,
"EMAIL_ID" character varying(70) COLLATE pg_catalog."default" NOT NULL,
"DESK_NUMBER" bigint,
"MOBILE_NUMBER" bigint,
"IS_ACTIVE" boolean NOT NULL DEFAULT true,
"CREATED_BY" character varying(70) COLLATE pg_catalog."default",
"MODIFIED_BY" character varying(70) COLLATE pg_catalog."default",
"DATE_CREATED" timestamp without time zone,
"DATE_MODIFIED" timestamp without time zone,
CONSTRAINT "USER_ID_PK" PRIMARY KEY ("USER_ID"),
CONSTRAINT "EMAIL_ID_UK" UNIQUE ("EMAIL_ID"),
CONSTRAINT "MOBILE_NUMBER_UK" UNIQUE ("MOBILE_NUMBER")
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
ALTER TABLE "USER_MGMT"."USER"
OWNER to postgres;
I am creating an JPA entity for this user table,
#Entity
#Table(name = "`USER`")
#ToString
#EqualsAndHashCode
public class User extends Auditable<String> {
/**
*
*/
private static final long serialVersionUID = 5351767213835401599L;
#Id
#SequenceGenerator(name = "USER_ID", sequenceName = "USER_SEQ", allocationSize = 1)
//Tried this also but not works
#SequenceGenerator(name = "USER_ID", sequenceName = "`USER_SEQ`", allocationSize = 1)
#GeneratedValue(generator = "USER_ID", strategy = GenerationType.SEQUENCE)
#Column(name = "`USER_ID`")
private Long userId;
#Column(name = "`FIRST_NAME`")
private String firstName;
While inserting data to this user table, I am getting error says user_seq is not available.
ERROR: relation "USER_MGMT.user_seq" does not exist
It tooks as lower case even though I mentioned in Upper case in entity.This is must for upper case for all the tables and sequences. Is there anything I missed in entity?

Related

Get list of database errors on saveAll()

I have a CountryObject:
#Entity
#Table(name = "country")
class CountryObject(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
val id: Long? = null,
#Column(name = "name")
val name: String,
#Column(name = "ISO2", length = 2)
val ISO2: String,
#Column(name = "ISO3", length = 3)
val ISO3: String
) : Serializable
with the corresponding PostgreSQL create script that has some unique constraints on ISO2 and ISO3:
CREATE TABLE country
(
id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,
iso2 VARCHAR(2) NOT NULL,
iso3 VARCHAR(3) NOT NULL,
CONSTRAINT pk_country PRIMARY KEY (id)
);
ALTER TABLE country
ADD CONSTRAINT UNIQUE_CONSTRAINT_ISO2 UNIQUE (iso2);
ALTER TABLE country
ADD CONSTRAINT UNIQUE_CONSTRAINT_ISO3 UNIQUE (iso3);
Along with this I have a corresponding repository:
#Repository
interface CountryRepository : JpaRepository<CountryObject, Long>
And out of the box implementation of the CountryRepository has a saveAll() method that tries to insert a list of objects into the country table. So far, everything behaves as expected.
Once I try to insert a list that have multiple objects violating the unique constraints, the exception is thrown on the first and stopped. What I want to have is to get some list with the errors that I can use as a report, which mentions which entries failed saving. Of course nothing should be saved in that case and the transaction is rolled back.
Any hints how something like this can me achieved? Of course one option would be to try to save each object separately and then collect the errors, but that might be not that performant.

Spring data JPA Teradata: Conversion between BYTE data and other types is illegal

I am not able to insert a record into the table.
Save method
#Modifying
#Query(value = "LOCKING TABLE JOB_QUEUE FOR WRITE INSERT INTO JOB_QUEUE (FILE_GUID, FILE_TYPE, PIPELINE_NAME, STATE, PRIORITY, DATE_CREATED, REQUEST_USER_ID, SPLIT_BY_BUS, FILTER_ID, GROUP_BY_BUS, RULE_SET, MAP_ID, OUTPUT_PATH, IS_REPLAY, SUBSCRIBING_PARTNER) VALUES (:#{#entity.fileGuid}, :#{#entity.fileType}, :#{#entity.pipelineName}, :#{#entity.state}, :#{#entity.priority}, :#{#entity.dateCreated}, :#{#entity.requestUserId}, :#{#entity.splitByBus}, :#{#entity.filterId}, :#{#entity.groupByBus}, :#{#entity.ruleSet}, :#{#entity.mapId}, :#{#entity.outputPath}, :#{#entity.isReplay}, :#{#entity.subscribingPartner})", nativeQuery = true)
<S extends JobQueue> void saveJobQueue(S entity);
Model Class
#Entity
#Table(
name = "JOB_QUEUE"
)
public class JobQueue implements Serializable {
private static final long serialVersionUID = 1L;
#Column(
name = "DATE_CREATED"
)
private Timestamp dateCreated;
#Column(
name = "FILE_GUID"
)
private String fileGuid;
#Column(
name = "FILE_TYPE"
)
private String fileType;
#Column(
name = "FILTER_ID"
)
private Long filterId;
#Column(
name = "GROUP_BY_BUS"
)
private BigDecimal groupByBus;
#Id
#GeneratedValue(
strategy = GenerationType.IDENTITY
)
private Long id;
#Column(
name = "IS_REPLAY"
)
private BigDecimal isReplay;
#Column(
name = "MAP_ID"
)
private Integer mapId;
#Column(
name = "OUTPUT_PATH"
)
private String outputPath;
#Column(
name = "PIPELINE_NAME"
)
private String pipelineName;
private Integer priority;
#Column(
name = "REQUEST_USER_ID"
)
private String requestUserId;
#Column(
name = "RULE_SET"
)
private String ruleSet;
#Column(
name = "SPLIT_BY_BUS"
)
private BigDecimal splitByBus;
private String state;
#Column(
name = "SUBSCRIBING_PARTNER"
)
private String subscribingPartner;
}
Table schema
CREATE SET TABLE JOB_QUEUE ,NO FALLBACK ,
NO BEFORE JOURNAL,
NO AFTER JOURNAL,
CHECKSUM = DEFAULT,
DEFAULT MERGEBLOCKRATIO,
MAP = TD_MAP1
(
ID BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY
(START WITH 1
INCREMENT BY 1
MINVALUE 0
MAXVALUE 999999999999999999
NO CYCLE),
FILE_GUID VARCHAR(250) CHARACTER SET LATIN NOT CASESPECIFIC,
FILE_TYPE VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC,
PIPELINE_NAME VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC NOT NULL,
STATE VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC NOT NULL,
PRIORITY INTEGER NOT NULL,
DATE_CREATED TIMESTAMP(6) NOT NULL,
REQUEST_USER_ID VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
SPLIT_BY_BUS NUMBER(1,0),
FILTER_ID BIGINT,
GROUP_BY_BUS NUMBER(1,0),
RULE_SET VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC,
MAP_ID INTEGER,
OUTPUT_PATH VARCHAR(500) CHARACTER SET LATIN NOT CASESPECIFIC,
IS_REPLAY NUMBER(1,0) DEFAULT 0 ,
SUBSCRIBING_PARTNER VARCHAR(100) CHARACTER SET LATIN NOT CASESPECIFIC)
UNIQUE PRIMARY INDEX JOB_QUEUE_UPI ( ID );
On execution I get the following exception
2021-08-05T00:30:15,800 ERROR [http-nio-8080-exec-1] o.h.e.j.s.SqlExceptionHelper: [Teradata Database] [TeraJDBC 16.20.00.12] [Error 3532] [SQLState 22018] Conversion between BYTE data and other types is illegal.
2021-08-05T00:30:16,465 ERROR [http-nio-8080-exec-1] o.a.j.l.DirectJDKLog: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not execute statement] with root cause
java.sql.SQLException: [Teradata Database] [TeraJDBC 16.20.00.12] [Error 3532] [SQLState 22018] Conversion between BYTE data and other types is illegal.
UPADTE
Null values were getting mapped to VARBINARY its resolved using Hibernate type mappings.
Query query = entityManager.createNativeQuery("LOCKING TABLE JOB_QUEUE FOR WRITE INSERT INTO JOB_QUEUE (FILE_GUID, FILE_TYPE, PIPELINE_NAME, STATE, PRIORITY, DATE_CREATED, REQUEST_USER_ID, SPLIT_BY_BUS, FILTER_ID, GROUP_BY_BUS, RULE_SET, MAP_ID, OUTPUT_PATH, IS_REPLAY, SUBSCRIBING_PARTNER) VALUES (CAST(:fileGuid AS VARCHAR(250)), CAST(:fileType AS VARCHAR(100)), CAST(:pipelineName AS VARCHAR(100)), CAST(:state AS VARCHAR(100)), :priority, :dateCreated, CAST(:requestUserId AS VARCHAR(10)), :splitByBus, :filterId, :groupByBus, CAST(:ruleSet AS VARCHAR(100)), :mapId, CAST(:outputPath AS VARCHAR(500)), :isReplay, CAST(:subscribingPartner AS VARCHAR(100)))")
.setParameter("fileGuid", new TypedParameterValue(StandardBasicTypes.STRING, entity.getFileGuid()))
.setParameter("fileType", new TypedParameterValue(StandardBasicTypes.STRING, entity.getFileType()))
.setParameter("pipelineName",
new TypedParameterValue(StandardBasicTypes.STRING, entity.getPipelineName()))
.setParameter("state", new TypedParameterValue(StandardBasicTypes.STRING, entity.getState()))
.setParameter("priority", new TypedParameterValue(StandardBasicTypes.INTEGER, entity.getPriority()))
.setParameter("dateCreated",
new TypedParameterValue(StandardBasicTypes.TIMESTAMP, entity.getDateCreated()))
.setParameter("requestUserId",
new TypedParameterValue(StandardBasicTypes.STRING, entity.getRequestUserId()))
.setParameter("splitByBus",
new TypedParameterValue(StandardBasicTypes.INTEGER, entity.getSplitByBus().intValue()))
.setParameter("filterId", new TypedParameterValue(StandardBasicTypes.INTEGER, entity.getFilterId()))
.setParameter("groupByBus", new TypedParameterValue(StandardBasicTypes.INTEGER, entity.getGroupByBus()))
.setParameter("ruleSet", new TypedParameterValue(StandardBasicTypes.STRING, entity.getRuleSet()))
.setParameter("mapId", new TypedParameterValue(StandardBasicTypes.INTEGER, entity.getMapId()))
.setParameter("outputPath", new TypedParameterValue(StandardBasicTypes.STRING, entity.getOutputPath()))
.setParameter("isReplay", new TypedParameterValue(StandardBasicTypes.INTEGER, entity.getIsReplay()))
.setParameter("subscribingPartner",
new TypedParameterValue(StandardBasicTypes.STRING, entity.getSubscribingPartner()));
query.executeUpdate();

MyBatis returns some columns as null, 0

I am using MyBatis and Spring Boot. I am trying to extract data from the db using this:
<select id="queryDeviceList" resultType="DeviceList">
SELECT id, mac_address, is_active
FROM ct_device_list dl
where dl.is_active = 1
</select>
and my POJO is
#Data
public class DeviceList {
private int id;
private String mac_address;
private int is_active;
}
and my DAO is
List <DeviceList> queryDeviceList();
and my table CT_DEVICE_LIST in Oracle db has
CREATE TABLE CT_DEVICE_LIST
(
ID NUMBER(10,0) NOT NULL
, MAC_ADDRESS VARCHAR2(17) NOT NULL
, IS_ACTIVE NUMBER(1) NOT NULL
, CREATED_DATE DATE NOT NULL
, CONSTRAINT CT_DEVICE_LIST_PK PRIMARY KEY
(
ID
)
ENABLE
);
But the results I got is:
id=1, mac_address=null, is_active = 0
but my mac_address has value and is_active is not 0 in the database.
Please help. Thanks.
if you set mybatis.configuration.map-underscore-to-camel-case=true, you should use
#Data
public class DeviceList {
private Integer id;
private String macAddress;
private Integer isActive;
}
Remember not to use primitive type int, if you don't want set default to 0.

JPA query after save doesn't return database generated field

I'm trying to save this model to a database, and then retrieve what I just saved. Every field is retrieved except for the database generated UUID field.
#Entity
#Table(name = "usertoken")
public class UserToken implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "token", insertable = false, updatable = false, nullable = false)
private UUID token;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="usersid", nullable=false)
private User user;
#Column(name = "expiration", updatable = false, nullable = false)
private LocalDateTime expiration;
I save the token from within the service
token = tokenRepository.save(token);
which generates this SQL
Hibernate:
insert
into
usertoken
(expiration, usersid)
values
(?, ?)
The next statement gets the token
token = tokenRepository.findByUser(user);
I see the SQL select includes the token field
Hibernate:
select
usertoken0_.id as id1_8_,
usertoken0_.expiration as expirati2_8_,
usertoken0_.token as token3_8_,
usertoken0_.usersid as usersid4_8_
from
usertoken usertoken0_
where
usertoken0_.usersid=?
...but the returned object has every field populated BUT the token. The database does have a value in the token column.
I'm at a loss as to why it would populate every field but one.
Here's the table in question:
CREATE TABLE public.usertoken
(
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
usersid integer NOT NULL,
token uuid NOT NULL DEFAULT uuid_generate_v1(),
expiration timestamp without time zone NOT NULL,
CONSTRAINT "usertoken_pkey" PRIMARY KEY (id)
)
I forgot to add that when I query later on the token is found and the UUID field is properly populated. So something weird with JPA caching? Are database DEFAULT column values ignored by hibernate after the insert?
tokenRepository.findByToken(UUID.fromString(userToken));
Hibernate:
select
usertoken0_.id as id1_8_,
usertoken0_.expiration as expirati2_8_,
usertoken0_.token as token3_8_,
usertoken0_.usersid as usersid4_8_
from
usertoken usertoken0_
where
usertoken0_.token=?
You have to signal hibernate that field is being generated by database. So add the following:
#org.hibernate.annotations.Generated(value = GenerationTime.INSERT)
#Column(name = "token", insertable = false,
updatable = false, nullable = false)
private UUID token;
You will also see hibernate issues a select just for that column after insert

Hibernate MapKeyManyToMany gives composite key where none exists

I have a Hibernate (3.3.1) mapping of a map using a three-way join table:
#Entity
public class SiteConfiguration extends ConfigurationSet {
#ManyToMany
#MapKeyManyToMany(joinColumns=#JoinColumn(name="SiteTypeInstallationId"))
#JoinTable(
name="SiteConfig_InstConfig",
joinColumns = #JoinColumn(name="SiteConfigId"),
inverseJoinColumns = #JoinColumn(name="InstallationConfigId")
)
Map<SiteTypeInstallation, InstallationConfiguration>
installationConfigurations = new HashMap<SiteTypeInstallation, InstallationConfiguration>();
...
}
The underlying table (in Oracle 11g) is:
Name Null Type
------------------------------ -------- ----------
SITECONFIGID NOT NULL NUMBER(19)
SITETYPEINSTALLATIONID NOT NULL NUMBER(19)
INSTALLATIONCONFIGID NOT NULL NUMBER(19)
The key entity used to have a three-column primary key in the database, but is now redefined as:
#Entity
public class SiteTypeInstallation implements IdResolvable {
#Id
#GeneratedValue(generator="SiteTypeInstallationSeq", strategy= GenerationType.SEQUENCE)
#SequenceGenerator(name = "SiteTypeInstallationSeq", sequenceName = "SEQ_SiteTypeInstallation", allocationSize = 1)
long id;
#ManyToOne
#JoinColumn(name="SiteTypeId")
SiteType siteType;
#ManyToOne
#JoinColumn(name="InstalationRoleId")
InstallationRole role;
#ManyToOne
#JoinColumn(name="InstallationTypeId")
InstType type;
...
}
The table for this has a primary key 'Id' and foreign key constraints+indexes for each of the other columns:
Name Null Type
------------------------------ -------- ----------
SITETYPEID NOT NULL NUMBER(19)
INSTALLATIONROLEID NOT NULL NUMBER(19)
INSTALLATIONTYPEID NOT NULL NUMBER(19)
ID NOT NULL NUMBER(19)
For some reason, Hibernate thinks the key of the map is composite, even though it isn't, and gives me this error:
org.hibernate.MappingException: Foreign key (FK1A241BE195C69C8:SiteConfig_InstConfig [SiteTypeInstallationId])) must have same number of columns as the referenced primary key (SiteTypeInstallation [SiteTypeId,InstallationRoleId])
If I remove the annotations on installationConfigurations and make it transient, the error disappears.
I am very confused why it thinks SiteTypeInstallation has a composite key at all when #Id is clearly defining a simple key, and doubly confused why it picks exactly just those two columns. Any idea why this happens? Is it possible that JBoss (5.0 EAP) + Hibernate somehow remembers a mistaken idea of the primary key across server restarts and code redeployments?
Thanks in advance,
-Lars

Resources