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

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();

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.

jpa generated schema doesn't include property of extended class

I've a very complex database which i will try to resume in here
#Embeddable
open class ChargeableDTO(
#NotBlank var name: String,
#NotBlank var ref: String,
#Min(1) var priceCents: Int,
#NotNull #Min(1) #Max(12) var maxInstallments: Int = 1,
#NotNull var gateway: PaymentGateway) {
#Embeddable
class CreditPackageDTO(name: String,
ref: String,
priceCents: Int,
maxInstallments: Int = 1,
gateway: PaymentGateway,
#Min(1) var creditAmount : Int) : ChargeableDTO(name, ref, priceCents, maxInstallments, gateway) {
#Entity
#Table(name = "credit_packages", uniqueConstraints = [UniqueConstraint(columnNames = ["gateway", "ref"])])
class CreditPackage(dto: CreditPackageDTO) : ChargeableEntity(dto)
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
abstract class ChargeableEntity(#field:Embedded open var dto: ChargeableDTO) : HydraEntity()
many other classes that are not relevant to this problem....
but when running the schema generation script hibernate generates a code like
create table credit_packages (
id bigint not null,
created_date datetime(6),
last_modified_date datetime(6),
public_id varchar(255),
gateway integer,
max_installments integer not null,
name varchar(255),
price_cents integer not null,
ref varchar(255),
primary key (id)
) engine=InnoDB
the first 4 fields come from a parent class which all my entities inherit from.
but this schema complete ignores the property creditAmount which is defined in the extended dto
also this code doesn't metion the limit 1 to 12 for maxinstallments
am i doing anything wrong, how can i fix it?

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.

Why doesn't Mybatis map a simple ENUM correctly?

I'm not doing anything out of the ordinary from what I can tell. I have a spring boot application using mybatis:
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'
I have an application.properties config for mybatis that is pretty simple:
## MyBatis ##
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-statement-timeout=30
My database table looks like this:
CREATE TABLE workspace_external_references (
id CHAR(36) PRIMARY KEY,
workspace_id CHAR(36) NOT NULL,
site VARCHAR(255) NOT NULL,
external_id VARCHAR(255) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT NOW(6),
updated_at DATETIME(6) NOT NULL DEFAULT NOW(6),
FOREIGN KEY (workspace_id) REFERENCES workspaces (id) ON DELETE CASCADE
)
With just a single entry like this:
'a907c0af-216a-41e0-b16d-42107a7af05f', 'e99e4ab4-839e-405a-982b-08e00fbfb2d4', 'ABC', '6', '2020-06-09 00:19:20.135822', '2020-06-09 00:19:20.135822'
In my mapper file I'm doing a select of all references like this:
#Select("SELECT * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(#Param("workspaceId") final UUID workspaceId);
And the java object that this is supposed to map to looks like this:
public class WorkspaceExternalReference {
private UUID id;
private UUID workspaceId;
private Sites site;
private String externalId;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public WorkspaceExternalReference(
final Sites site,
final UUID workspaceId,
final String externalId) {
this.site = site;
this.workspaceId = workspaceId;
this.externalId = externalId;
}
}
public enum Sites {
ABC, XYZ;
}
Sooooo why doesn't this work? I get this error back:
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'id' from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.acme.Sites.a907c0af-216a-41e0-b16d-42107a7af05f
When there is no default constructor, you need to let MyBatis know which columns to pass to the constructor explicitly (in most cases).
With annotations, it would look as follows.
You can use <resultMap> and <constructor> in XML mapper.
#ConstructorArgs({
#Arg(column = "site", javaType = Sites.class),
#Arg(column = "workspace_id", javaType = UUID.class),
#Arg(column = "external_id", javaType = String.class)
})
#Select("SELECT * FROM workspace_external_references WHERE workspace_id = #{workspaceId}")
List<WorkspaceExternalReference> findByWorkspace(#Param("workspaceId") final UUID workspaceId);
Other columns (i.e. id, created_at, updated_at) will be auto-mapped via setters (if there are) or reflection.
Alternatively, you can just add the default (no-arg) constructor to the WorkspaceExternalReference class. Then all columns will be auto-mapped after the class is instantiated.
Note: To make it work, there needs to be a type handler registered for UUID, but you seem to have done it already (otherwise the parameter mapping wouldn't work).

Spring Boot + PostgreSql Sequence not available

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?

Resources