H2 database insert null to primary key - java

I have created the table in the H2 database as follows:
CREATE OR REPLACE SEQUENCE IF NOT EXISTS SCMSA_HIST.KEY_GEN_SEQ
START WITH 0
INCREMENT BY 1
NOCYCLE
NOCACHE;
CREATE TABLE IF NOT EXISTS SCMSA_HIST.SCMSA_POS_TRANS_ROLLUP
(
POS_TRANS_ID INTEGER DEFAULT
(NEXT VALUE FOR SCMSA_HIST.KEY_GEN_SEQ)
NOT NULL IDENTITY ,
JOB_LOG_ID INTEGER,
DEALER_CODE VARCHAR(255),
STORE_ID VARCHAR(255),
TRANSACTION_DT TIMESTAMP,
QUANTITY INTEGER,
ROLLUP_TYPE VARCHAR(255),
CREATE_DT TIMESTAMP,
MAX_TRANSACTION_DT TIMESTAMP,
PROCESSED_FLAG VARCHAR(255),
CREATE_MONTH INTEGER,
CREATE_YEAR INTEGER
);
The Model class for the above table is as follows:
#Entity
#Table(schema = "SCMSA_HIST", name = "SCMSA_POS_TRANS_ROLLUP")
public class ScmsaPosTransRollup {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ")
#SequenceGenerator(name = "SEQ", sequenceName = "SCMSA_HIST.KEY_GEN_SEQ")
#Column(name = "POS_TRANS_ID")
private Long posTransId;
#Column(name = "JOB_LOG_ID")
private Long jobLogId;
#Column(name = "DEALER_CODE")
private String dealerCode;
#Column(name = "STORE_ID")
private String storeId;
#Column(name = "TRANSACTION_DT")
private Timestamp transactionDate;
#Column(name = "ROLLUP_TYPE")
private String rollupType;
#Column(name = "QUANTITY")
private Integer quantity;
#Column(name = "CREATE_DT")
private Timestamp createDate;
#Column(name = "MAX_TRANSACTION_DT")
private Timestamp maxTransactionDate;
#Column(name = "PROCESSED_FLAG")
private String processedFlag;
#Column(name = "CREATE_MONTH", insertable = false, updatable = false)
private Integer createMonth;
#Column(name = "CREATE_YEAR", insertable = false, updatable = false)
private Integer createYear;
public ScmsaPosTransRollup() {
}
//getter and setter
}
But, when I am trying to insert , the value for the "POS_TRANS_ID" is inserted as null. Can anyone please suggest me what am doing wrong here.

I tried to reproduce your problem. What helps to me:
1. Scripts
CREATE OR REPLACE SEQUENCE IF NOT EXISTS KEY_GEN_SEQ
MINVALUE 1
MAXVALUE 999999999999999999
START WITH 1
INCREMENT BY 500
NOCYCLE
NOCACHE;
In create table DDL I replaced ID creation
POS_TRANS_ID INTEGER DEFAULT KEY_GEN_SEQ.NEXTVAL
NOT NULL IDENTITY ,
In Java class added initialValue and allocationSize to #SequenceGenerator, and changed strategy to SEQUENCE
#GeneratedValue(strategy=SEQUENCE, generator="SEQ")
#SequenceGenerator(name = "SEQ", sequenceName = "KEY_GEN_SEQ",initialValue = 1,allocationSize = 500)
And don't forget to define dialect in Hibernate props
hibernate.dialect=org.hibernate.dialect.H2Dialect

Related

JPA auto-ddl , setting Long value length not work

#Data
#Entity
#Table(name = "test_jpa")
public class TestEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id",length = 19)
private Long id;
#Column(name = "length",precision = 10)
private Long length;
#Column(name = "test", length = 19)
private String test;
}
Log print:
Hibernate: create table test_jpa (id bigint not null, length bigint, test varchar(19), primary key (id)) engine=InnoDB
The length of Long value ,do not work.Also I tried #Size and #Length, same problem.
JPA version:2.6.7
Mysql
Thank you M. Deinum.
I get it, Numeric types no need to set length,They have fixed range.

How to fix automatic bigint generation in spring boot for table column

I have a spring boot application with two entities in a relationship. MeetingSetting and MeetingTime meetingSetting can have unlimited meetingTimes. So far the databases are generating without problem and I can halfway save the values as well. But there is one problem. meetingName is a string and used as a foreign key in meetingTime but when the database are generated for some reason it is added as a bigint and I could not find the reason for that, because everywhere it is used as string. Could someone look at my code and tell me my mistake?
MeetingSettings:
#Entity
#Table(name = "meeting_settings")
#Data
public class MeetingsSetting {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_name", unique = true)
private String meetingName;
#Column(name = "meeting_url")
private String meetingUrl;
#Column(name = "meeting_pw")
private String meetingPw;
#OneToMany(mappedBy = "meeting_Name", cascade = CascadeType.ALL)
private Set<MeetingTime> meetingTime = new HashSet<>();
}
MeetingTime:
#Entity
#Table(name = "meeting_times")
#Data
public class MeetingTime {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "end_time")
private String endTime;
#ManyToOne
#JoinColumn(name = "meeting_name" ,insertable = false, updatable = false)
private MeetingsSetting meeting_Name;
}
This is my application property:
spring.datasource.url=jdbc:mysql://localhost:3306/coorporate_blinddate?createDatabaseIfNotExist=true&useSSL=true&serverTimezone=UTC
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=../generate.sql
spring.jpa.show-sql= true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto = update
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=Test1234##1
server.port=8081
and the script used for db generation:
-- auto-generated definition
create table meeting_settings
(
id bigint auto_increment
primary key,
meeting_name varchar(255) null,
meeting_pw varchar(255) null,
meeting_url varchar(255) null
);
-- auto-generated definition
create table meeting_times
(
id bigint auto_increment
primary key,
meeting_date varchar(255) null,
start_time varchar(255) null,
end_time varchar(255) null,
meeting_name varchar(255) null,
constraint fk_meeting_times_meeting_name
foreign key (meeting_name) references meeting_settings (meeting_name)
);
I fixed this with the big int by adding referencedColumnName = "meeting_name" to this in meetingTime:
#ManyToOne
#JoinColumn(name = "meeting_name" ,insertable = false, updatable = false)
private MeetingsSetting meeting_Name;
changed to:
#ManyToOne
#JoinColumn(name = "meeting_name" ,insertable = false, updatable = false, referencedColumnName = "meeting_name")
private MeetingsSetting meeting_Name;

How to create two entities and relate them

First of all, apologize for the grammatical errors that you can make. My English is not very good.
I'm trying to create dinamically an Entity and relathion with other Entity.
The idea is send a json file and get some properties to create that Entity, later associate that entity with the other. However, I can't because throw Exception like:
attempted to assign id from null one-to-one property
So, here in my SchemeService I try to create both entities:
protected Scheme createScheme(final String creatorId, final String name, final String description, final InputStream inputStream) {
DeserializeJSONFile desJsonFile = new DeserializeJSONFile();
desJsonFile.init(inputStream);
TableEntity table = new TableEntity();
table.setCreator(creatorId);
table.setProperties(desJsonFile.getProperties().toString());
table.setGeometry(desJsonFile.getGeometry().toString());
createTable(table);
Scheme scheme = new Scheme();
scheme.setCreator(creatorId);
scheme.setName(name);
scheme.setDescription(description);
scheme.setTable(table);
createScheme(scheme);
return scheme;
}
private void createTable(final TableEntity table) {
tableDao.create(table);
}
protected void createScheme(final Scheme scheme) {
schemeDao.create(scheme);
}
Here is my TableEntity:
public class TableEntity extends BaseEntityActivable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SCHEME_SEQ_GEN")
#SequenceGenerator(name = "SCHEME_SEQ_GEN", sequenceName = "test_seq_table", allocationSize = 1)
#Column(name = "table_id")
private Long tableId;
#Type(type= "jsonb")
#Column(name = "properties", columnDefinition = "json")
private String properties;
#Type(type= "jsonb")
#Column(name = "geometry", columnDefinition = "json")
private String geometry;
#OneToOne
#MapsId
private Scheme scheme;
}
Here is my SchemeEntity:
public class Scheme extends BaseEntityActivable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SCHEME_SEQ_GEN")
#SequenceGenerator(name = "SCHEME_SEQ_GEN", sequenceName = "test_seq_scheme", allocationSize = 1)
#Column(name = "scheme_id")
private Long schemeId;
#Column(name = "name", nullable = false)
#NotEmpty(message = AxisMapsErrorConstants.NAME_CANT_BE_EMPTY)
private String name;
#Column(name = "description")
private String description;
#OneToOne(mappedBy = "scheme", cascade = CascadeType.ALL)
#JoinColumn(name = "scheme_id", referencedColumnName = "table_id", foreignKey = #ForeignKey(name = "fk_scheme_table_1"))
private TableEntity table;
}
Here is my sql:
create sequence test_seq_table start 1 increment 1;
create sequence test_seq_scheme start 1 increment 1;
create table maps_table (
table_id int8 not null,
created_at timestamp not null,
created_by varchar(255),
updated_at timestamp,
updated_by varchar(255),
is_active boolean not null,
properties jsonb not null,
geometry jsonb not null,
primary key (table_id)
);
create table maps_scheme (
scheme_id int8 not null,
created_at timestamp not null,
created_by varchar(255),
updated_at timestamp,
updated_by varchar(255),
is_active boolean not null,
description varchar(255),
name varchar(255) not null,
table_id int8 not null,
primary key (scheme_id)
);
alter table maps_scheme
add constraint fk_scheme_table_1
foreign key (scheme_id)
references maps_table;
since you are using #mapsId this means you are using the same identifier in your relation with scheme, which means first the scheme should not be nullable and it should be available as managed entity each time your object is flushed, which also means that you can do the persistence only from one side of the relation since the id of scheme should be available when persisting your entity.
I am not sure if you really need #mapsId here, since you already have a bidirectional relation which means anyway you will be able to access both sides of your entity.
I would suggest to remove #mapsId here.
Thanks everyone for helping me.
This is my solution.
Scheme:
public class Scheme extends BaseEntityActivable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SCHEME_SEQ_GEN")
#SequenceGenerator(name = "SCHEME_SEQ_GEN", sequenceName = "aguas_seq_scheme", allocationSize = 1)
#Column(name = "scheme_id")
private Long schemeId;
#Column(name = "name", nullable = false)
#NotEmpty(message = AxisMapsErrorConstants.NAME_CANT_BE_EMPTY)
private String name;
#Column(name = "description")
private String description;
#OneToOne(cascade= { CascadeType.ALL }, fetch = FetchType.LAZY)
#JoinColumn(name="table_id")
private TableEntity table;
}
TableEntity:
public class TableEntity extends BaseEntityActivable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SCHEME_SEQ_GEN")
#SequenceGenerator(name = "SCHEME_SEQ_GEN", sequenceName = "aguas_seq_table", allocationSize = 1)
#Column(name = "table_id")
private Long tableId;
#Type(type= "jsonb")
#Column(name = "properties", columnDefinition = "json")
private String properties;
#Type(type= "jsonb")
#Column(name = "geometry", columnDefinition = "json")
private String geometry;
#OneToOne(mappedBy= "table")
private Scheme scheme;
}
SQL:
create sequence aguas_seq_table start 1 increment 1;
create sequence aguas_seq_scheme start 1 increment 1;
create table maps_table (
table_id int8 not null,
created_at timestamp not null,
created_by varchar(255),
updated_at timestamp,
updated_by varchar(255),
is_active boolean not null,
properties jsonb not null,
geometry jsonb not null,
primary key (table_id)
);
create table maps_scheme (
scheme_id int8 not null,
created_at timestamp not null,
created_by varchar(255),
updated_at timestamp,
updated_by varchar(255),
is_active boolean not null,
description varchar(255),
name varchar(255) not null,
table_id int8 not null,
primary key (scheme_id)
);
SchemeService to create scheme and table:
protected Scheme createScheme(final String creatorId, final String name, final String description, final InputStream inputStream) {
DeserializeJSONFile desJsonFile = new DeserializeJSONFile();
desJsonFile.init(inputStream);
TableEntity table = new TableEntity();
table.setCreator(creatorId);
table.setGeometry(desJsonFile.loadGeometries().toString());
table.setProperties(desJsonFile.loadProperties().toString());
createTable(table);
Scheme scheme = new Scheme();
scheme.setCreator(creatorId);
scheme.setName(name);
scheme.setDescription(description);
scheme.setTable(table);
createScheme(scheme);
return scheme;
}

JPA many-to-one with constant values in referenced table

I'm doing Spring Boot project and use spring-boot-jpa (Hibernate implementation). I'm having trouble configuring following relation between entities.
Let's assume I need many-to-one (and reversly one-to-many) relation between two tables (MySQL in this example, table1 logically stores description for codes in various other tables) :
CREATE TABLE `table1` (
`id` INT NOT NULL AUTO_INCREMENT,
`ref_table` VARCHAR(50) NOT NULL,
`ref_column` VARCHAR(50) NOT NULL,
`code` VARCHAR(10) NOT NULL,
`description` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `u_composite1` (`ref_table` ASC, `ref_column` ASC, `code` ASC));
CREATE TABLE `table2` (
`id` INT NOT NULL AUTO_INCREMENT,
`field1` VARCHAR(100) NULL,
`code` VARCHAR(10) NOT NULL,
PRIMARY KEY (`id`));
The way I join these two tables in SQL is like this:
SELECT t2.*, t1.description
FROM table2 t2
JOIN table1 t1
ON ( t1.ref_table = 'table2'
AND t1.ref_column = 'code'
AND t1.code = t2.code);
So, I created entities like this (minus the getters an setters):
#Entity
#Table(name = "table1")
public class Table1 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private int id;
#Column(nullable = false, length = 10)
private String code;
#Column(length = 100)
private String description;
#Column(name = "ref_column", nullable = false, length = 50)
private String refColumn;
#Column(name = "ref_table", nullable = false, length = 50)
private String refTable;
#OneToMany(mappedBy = "table1")
private List<Table2> table2;
}
#Entity
#Table(name = "table2")
public class Table2 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false)
private int id;
#Column(nullable = false, length = 45)
private String field1;
#ManyToOne(fetch=FetchType.LAZY)
#Column(name = "code")
#JoinColumns({
#JoinColumn(name = "code", referencedColumnName = "code", nullable = false, updatable = false),
#JoinColumn(name = "'table2'", referencedColumnName = "ref_table", nullable = false, updatable = false),
#JoinColumn(name = "'code'", referencedColumnName = "ref_column", nullable = false, updatable = false)
})
private Table1 table1;
}
But it doesn't work. :(
Can this kind of relation even be defined in JPA?
If so, please, how?
Pertaining to the "join with constant values" problem I managed to make it work using the #Where Hibernate annotation:
How to replace a #JoinColumn with a hardcoded value?
#Entity
#Table(name = "a")
public class A {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public long id;
#OneToMany
#JoinColumn(name = "id", referencedColumnName = "id")
#Where(clause = "blah = 'CONSTANT_VALUE'")
public Set<B> b;
protected A() {}
}
#Entity
#Table(name = "b")
public class B {
#Id
#Column(nullable = false)
public Long id;
#Column(nullable = false)
public String blah;
protected B() {}
}

Database column requires int, but doesn't throw exception when string is inputted

I have a rest service which has a database. When I add an entity to my database in an EJB using a entityfacade, one entity variable price requires an real. If I input the price as a string in xml format from a client, no exception is thrown and the database registers 0 instead. If I make the variable too large the proper exception is thrown.
Any ideas of why this is happening? Or is there a way if setting my database table to accept integer only?
#Entity
#Table(name = "BOOKS", catalog = "", schema = "DAVID")
#XmlRootElement
public class Books implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
//#NotNull
#Column(name = "BOOKID")
private Integer bookid;
#Basic(optional = false)
#NotNull
#Column(name = "ISBN")
private long isbn;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 40)
#Column(name = "PUBLISHER")
private String publisher;
#Column(name = "QUANTITY")
private int quantity;
#Basic(optional = false)
#NotNull
#Column(name = "PRICE")
private float price;
CREATE TABLE BOOKS (BOOKID INTEGER DEFAULT AUTOINCREMENT: start 1 increment 1 NOT NULL GENERATED ALWAYS AS IDENTITY, ISBN BIGINT NOT NULL, TITLE VARCHAR(100) NOT NULL, COPYRIGHT VARCHAR(4) NOT NULL, PUBLISHER VARCHAR(40) NOT NULL, QUANTITY INTEGER, PRICE REAL NOT NULL, PRIMARY KEY (BOOKID));

Categories