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

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() {}
}

Related

Hibernate One-to-One, When inserting, Why FK is null

When I run this code, it is running with out error. But When I check the values, as you can see, In the "Tbl_InstructorDetail" table the parentId is null
can anyone help.
thank you.
This is my Entities and my main class with table relation
enter image description here
this is my tables from my database
create table Tbl_Instructor
(
uuid int identity
constraint Pk_Tbl_Instructor_uuid
primary key,
Title nvarchar(50)
)
create table Tbl_InstructorDetail
(
uuid int identity
constraint Pk_Tbl_InstructorDetail_uuid
primary key,
Created_By nvarchar(50),
parentId int
constraint Fk_Tbl_InstructorDetail_Tbl_Instructor
references Tbl_Instructor
)
#Entity
#Table(name = "Tbl_InstructorDetail", schema = "dbo", catalog = "OJT_2021_KST")
public class TblInstructorDetailEntity {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "uuid", nullable = false)
private int uuid;
#Basic
#Column(name = "Created_By", nullable = true, length = 50)
private String createdBy;
#Basic
#Column(name = "parentId", nullable = true,insertable = false,updatable = false)
private Integer parentId;
#OneToOne
#JoinColumn(name = "parentId",referencedColumnName="uuid")
private TblInstructorEntity instructorEntity;
#Entity
#Table(name = "Tbl_Instructor", schema = "dbo", catalog = "OJT_2021_KST")
public class TblInstructorEntity {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "uuid", nullable = false)
private int uuid;
#Basic
#Column(name = "Title", nullable = true, length = 50)
private String title;
#OneToOne(mappedBy="instructorEntity",cascade = CascadeType.ALL)
private TblInstructorDetailEntity detailEntity;
Main class
TblInstructorEntity instructor = new TblInstructorEntity();
instructor.setTitle("This is a Test");
TblInstructorDetailEntity detail = new TblInstructorDetailEntity();
detail.setCreatedBy("Kyle");
instructor.setDetailEntity(detail);
session.getTransaction().begin();
session.save(instructor);
session.getTransaction().commit();
You don't need to add parentId in TblInstructorDetailEntity because it's referenced from TblInstructorEntity. In main class foreign key pass null because you can take a reference to the parent table before save parent table.
Here down is modified code:
Entity
#Entity
#Table(name = "Tbl_InstructorDetail", schema = "dbo", catalog = "OJT_2021_KST")
public class TblInstructorDetailEntity {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "uuid", nullable = false)
private int uuid;
#Basic
#Column(name = "Created_By", nullable = true, length = 50)
private String createdBy;
// remove parentId column because it is foreign key
#OneToOne
#JoinColumn(name = "parentId",referencedColumnName="uuid")
private TblInstructorEntity instructorEntity;
// getter setter
}
#Entity
#Table(name = "Tbl_Instructor", schema = "dbo", catalog = "OJT_2021_KST")
public class TblInstructorEntity {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "uuid", nullable = false)
private int uuid;
#Basic
#Column(name = "Title", nullable = true, length = 50)
private String title;
#OneToOne(mappedBy="instructorEntity",cascade = CascadeType.ALL)
private TblInstructorDetailEntity detailEntity;
// getter setter
}
Main
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
TblInstructorEntity instructor = new TblInstructorEntity();
instructor.setTitle("This is a Test");
TblInstructorDetailEntity detail = new TblInstructorDetailEntity();
detail.setCreatedBy("Kyle");
session.save(instructor); // Save parent entity
detail.setInstructorEntity(instructor); // Reference from parent entity
session.save(detail); // Save child entity
session.getTransaction().commit();
HibernateUtil.shutdown();

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;

Many to many on delete set NULL

I have a many to many relationship between user and group with addtional columns in the join table. It looks like this:
When I delete an user, it should remove all his references from user_to_group(which works) and all the groups created by him should remain and have their created_by field updated to NULL(this doesn't happen, all the entries are deleted).
DDL for schema:
CREATE TABLE user (
user_id int NOT NULL AUTO_INCREMENT,
first_name varchar(100) NOT NULL,
last_name varchar(100) NOT NULL,
username varchar(100) NOT NULL,
email_address varchar(100) UNIQUE NOT NULL,
phone_number varchar(100) NOT NULL,
password varchar(255) NOT NULL,
notification_type varchar(30) NOT NULL DEFAULT "email",
date_created datetime NOT NULL,
is_active bool NOT NULL DEFAULT false,
CONSTRAINT user_pk PRIMARY KEY (user_id)
);
CREATE TABLE `group` (
group_id int NOT NULL AUTO_INCREMENT,
name varchar(100) NULL,
date_created datetime NOT NULL,
is_private bool NOT NULL DEFAULT false,
created_by int NULL,
CONSTRAINT group_pk PRIMARY KEY (group_id),
CONSTRAINT group_user_fk FOREIGN KEY(created_by)
REFERENCES user (user_id) ON DELETE SET NULL
);
CREATE TABLE user_to_group (
user_id int NOT NULL,
group_id int NOT NULL,
user_type_id int NOT NULL,
is_blocked bool NOT NULL DEFAULT false,
CONSTRAINT user_to_group_pk PRIMARY KEY (user_id,group_id),
CONSTRAINT user_to_group_group_fk FOREIGN KEY(group_id)
REFERENCES `group` (group_id),
CONSTRAINT user_to_group_user_type_fk FOREIGN KEY(user_type_id)
REFERENCES user_type (id),
CONSTRAINT user_to_group_user_fk FOREIGN KEY(user_id)
REFERENCES user (user_id)
);
User Entity:
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private Long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "username",
unique = true)
private String username;
#Column(name = "email_address",
unique = true)
private String emailAddress;
#Column(name = "phone_number")
private String phoneNumber;
#Column(name = "password")
private String password;
#Column(name = "notification_type",
insertable = false)
private String notificationType = "email";
#Column(name = "date_created")
private Date dateCreated;
#Column(name = "is_active",
insertable = false)
private Boolean active = false;
#OneToMany(
mappedBy = "user",
cascade = {CascadeType.DETACH, CascadeType.MERGE,
CascadeType.REFRESH, CascadeType.PERSIST},
orphanRemoval = true
)
private List<UserGroup> groups;
}
Group Entity:
#Entity
#Table(name = "`group`")
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_id")
private Long id;
#Column(name = "name")
private String name;
#Column(name = "date_created")
private Date dateCreated;
#Column(name = "is_private",
insertable = false)
private Boolean privateG = false;
#OneToOne(fetch = FetchType.LAZY,
cascade = {CascadeType.DETACH, CascadeType.MERGE,
CascadeType.REFRESH, CascadeType.PERSIST},
orphanRemoval = true)
#JoinColumn(name = "created_by")
private User createdBy;
#OneToMany(
mappedBy = "group",
cascade = {CascadeType.DETACH, CascadeType.MERGE,
CascadeType.REFRESH, CascadeType.PERSIST},
orphanRemoval = true
)
private List<UserGroup> users = new ArrayList<>();
}
UserGroup(join table):
#Entity
#Table(name = "user_to_group")
public class UserGroup {
#EmbeddedId
private UserGroupId id;
#ManyToOne(fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
#MapsId("userId")
#JoinColumn(name = "user_id", insertable = false, updatable = false)
private User user;
#ManyToOne(fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
#MapsId("groupId")
#JoinColumn(name = "group_id", insertable = false, updatable = false)
private Group group;
#Column(name = "is_blocked",
insertable = false)
private boolean isBlocked = false;
}
Ignore user_type_id field on the join table. If I delete an user with on the workbench, it works as expected(created_by field updates to NULL). But if i use this:
#Override
#Transactional
public User deleteUser(Long id) {
Optional<User> userToDelete = userRepository.findById(id);
userToDelete.ifPresent(user -> userRepository.delete(user));
return userToDelete.orElseThrow(() -> new UserNotFoundException("User not found"));
}
the entire row in the group table is deleted. What am I doing wrong?
#ManyToOne(fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
#MapsId("groupId")
#JoinColumn(name = "group_id", insertable = false, updatable = false)
private Group group;
exclude CascadeType.REMOVE and group will be intact.

DuplicateMappingException on created_by field

I have 2 tables employee and employee_document. Here is the mysql query for two tables -
CREATE TABLE employee (
id int(11) unsigned NOT NULL,
name varchar(100) COLLATE utf8_unicode_ci NOT NULL,
email varchar(50) COLLATE utf8_unicode_ci NOT NULL,
password_hash varchar(100) COLLATE utf8_unicode_ci NOT NULL,
status int(11) NOT NULL,
creation_date bigint(20) NOT NULL,
created_by int(11) DEFAULT NULL,
update_date bigint(20) NOT NULL,
updated_by int(11) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE employee_document (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
employee_id int(11) unsigned NOT NULL,
file_id int(11) unsigned NOT NULL,
document_type varchar(50) COLLATE utf8_unicode_ci DEFAULT '',
status int(11) DEFAULT NULL,
creation_date bigint(20) DEFAULT NULL,
created_by int(11) unsigned NOT NULL,
update_date bigint(20) DEFAULT NULL,
updated_by int(11) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
In my spring boot project I used hibernate with JPA Data. Here are the java interpretation of these tables.
#MappedSuperclass
public abstract class AbstractTimestampEntity {
#Transient
Logger log = LoggerFactory.getLogger(AbstractTimestampEntity.class);
#Column(name = "creation_date", nullable = false, updatable=false)
private Long creationDate;
#Column(name = "update_date", nullable = false)
private Long updateDate;
#PrePersist
protected void onCreate() {
log.debug("onCreate");
updateDate = creationDate = System.currentTimeMillis();
}
#PreUpdate
protected void onUpdate() {
log.debug("onUpdate");
updateDate = System.currentTimeMillis();
}
}
#Entity
#Table(name = "employee")
public class Employee extends AbstractTimestampEntity implements Serializable {
private static final long serialVersionUID = 1L;
public static final Integer STATUS_INACTIVE = 0;
public static final Integer STATUS_ACTIVE = 1;
public static final Integer STATUS_ARCHIVED = -1;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer id;
#Column(name = "name", nullable = false)
public String name;
#Email
#Column(name = "email", nullable = false, unique = true)
public String email;
#JsonIgnore
#Column(name = "password_hash", nullable = false)
public String passwordHash;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "employee", fetch = FetchType.EAGER)
private Set<EmployeeDocument> documents;
#Max(1)
#Min(-1)
#Column(name = "status", nullable = false )
public Integer status;
#Column(name = "created_by", updatable = false)
public Integer createdById;
#Column(name = "updated_by")
public Integer updatedById;
}
#Entity
#Table(name = "employee_document")
public class EmployeeDocument extends AbstractTimestampEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Transient
public static final Integer STATUS_INACTIVE = 0;
#Transient
public static final Integer STATUS_ACTIVE = 1;
#Transient
public static final Integer STATUS_ARCHIVED = -1;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer id;
#JsonIgnore
#ManyToOne
#JoinColumn(name = "employee_id", nullable = false)
public Employee employee;
#OneToOne
#JoinColumn(name = "file_id")
public EmployeeFile employeeFile;
#Max(1)
#Min(-1)
#Column(name = "status", nullable = false )
public Integer status;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "created_by", updatable = false)
#JsonBackReference
public Employee createdBy;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "updated_by")
#JsonBackReference
public Employee updatedBy;
}
This code does not execute, the app fails to start and throws DuplicateMappingException. Here's the full exception stack -
org.hibernate.DuplicateMappingException: Table [employee_document] contains physical column name [created_by] referred to by multiple physical column names: [createdBy], [created_by]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl$TableColumnNameBinding.bindPhysicalToLogical(InFlightMetadataCollectorImpl.java:922)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl$TableColumnNameBinding.addBinding(InFlightMetadataCollectorImpl.java:891)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.addColumnNameBinding(InFlightMetadataCollectorImpl.java:961)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.addColumnNameBinding(InFlightMetadataCollectorImpl.java:942)
at org.hibernate.cfg.Ejb3Column.addColumnBinding(Ejb3Column.java:407)
at org.hibernate.cfg.Ejb3Column.linkWithValue(Ejb3Column.java:369)
at org.hibernate.cfg.annotations.SimpleValueBinder.linkWithValue(SimpleValueBinder.java:431)
at org.hibernate.cfg.annotations.SimpleValueBinder.make(SimpleValueBinder.java:407)
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyAndValue(PropertyBinder.java:187)
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:199)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2225)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:911)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:738)
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:245)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:222)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:265)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
... 19 common frames omitted
What am I doing wrong? Thanks in advance.
You are trying to reference the Empolyee three times from the EmployeeDocument but only one of those is by primary key. The other two are referenced by non-primary key columns and you would need to use the referencedColumnName option additionally to make this work:
#JsonIgnore
#ManyToOne
#JoinColumn(name = "employee_id", nullable = false)
public Employee employee;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "created_by", referencedColumnName="created_by", updatable = false)
#JsonBackReference
public Employee createdBy;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "updated_by". , referencedColumnName="updated_by")
#JsonBackReference
public Employee updatedBy;

org.hibernate.exception.ConstraintViolationException: could not insert

When I try to add into TDEPOFAZLA table, I get the following error:
org.springframework.dao.DataIntegrityViolationException: could not insert: [tr.gov.tcmb.pgmtems.model.DepoFazla]; SQL [insert into PGMTEMS.TDEPOFAZLA (ID, FAZLABULUNDURMAORANI, GRUP) values (default, ?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [tr.gov.tcmb.pgmtems.model.DepoFazla]
Here is my JUnit test function:
#Test
public void testSaveDepoFazla() {
DepoTur depoTur = new DepoTur("my tür", 5);
depoTurService.saveDepoTur(depoTur);
List<DepoTur> list = depoTurService.getDepoTurList();
assertNotNull(list.get(0));
BigDecimal fazlaBulundurmaOrani = new BigDecimal(6000);
DepoFazla depoFazla = new DepoFazla(1, list.get(0), fazlaBulundurmaOrani);
depoFazlaService.saveDepoFazla(depoFazla);
}
Here is my DepoFazla.java:
#Entity
#Table(schema = "PGMTEMS", name = "TDEPOFAZLA")
public class DepoFazla implements Serializable {
private static final long serialVersionUID = -2800365387332643658L;
#Id
#GeneratedValue
#Column(name = "ID", nullable = false, updatable = false)
private Long id;
#Column(name = "GRUP", nullable = false, columnDefinition = "INTEGER")
private Integer grup;
#ManyToOne(fetch = FetchType.LAZY, targetEntity = DepoTur.class)
#JoinColumn(name = "ID", insertable = false, updatable = false)
#NotNull
private DepoTur depoTur;
#Column(name = "FAZLABULUNDURMAORANI", nullable = false, columnDefinition = "DECIMAL(6, 2)")
private BigDecimal fazlaBulundurmaOrani;
public DepoFazla() {
super();
}
public DepoFazla(Integer grup, DepoTur depoTur, BigDecimal fazlaBulundurmaOrani) {
super();
this.grup = grup;
this.depoTur = depoTur;
this.fazlaBulundurmaOrani = fazlaBulundurmaOrani;
}
//GETTER AND SETTER METHODS
}
Here is DepoTur.java:
#Entity
#Table(schema = "PGMTEMS", name = "TDEPOTUR")
public class DepoTur implements Serializable {
private static final long serialVersionUID = 6203672609079710060L;
#Id
#GeneratedValue
#Column(name = "ID", nullable = false, updatable = false)
#Index(name = "XUTDEPOTURP", columnNames = { "id" })
private Long id;
#Column(name = "ACIKLAMA", nullable = false)
private String aciklama;
#Column(name = "BLOKESIRASI", nullable = false)
private Integer blokeSirasi; //
#Column(name = "DEPOCINSI")
private String depoCinsi;
public DepoTur() {
super();
}
public DepoTur(String aciklama, Integer blokeSirasi, String depoCinsi) {
super();
this.aciklama = aciklama;
this.depoCinsi = depoCinsi;
this.blokeSirasi = blokeSirasi;
}
public DepoTur(String aciklama, Integer blokeSirasi) {
super();
this.aciklama = aciklama;
this.blokeSirasi = blokeSirasi;
}
//GETTER AND SETTER METHODS
When I debug the JUnit test, I get this error:
Error: DB2 SQL Error: SQLCODE=-407, SQLSTATE=23502, SQLERRMC=TBSPACEID=2, TABLEID=75, COLNO=2, DRIVER=3.50.152 SQLState: 23502 ErrorCode: -407
When I search the error, I find that I try to insert NULL but I can't figure out where I add null value.
This is how I create TDEPOFAZLA table:
CREATE TABLE TDEPOFAZLA
(
ID decimal(20,0) PRIMARY KEY NOT NULL,
GRUP int NOT NULL,
DEPOTUR decimal(20,0) NOT NULL,
FAZLABULUNDURMAORANI decimal(6,2) NOT NULL
);
CREATE UNIQUE INDEX XUTDEPOFAZLAP ON TDEPOFAZLA(ID);
This is how I create TDEPOTUR table:
CREATE TABLE TDEPOTUR
(
ID decimal(20,0) PRIMARY KEY NOT NULL,
ACIKLAMA varchar(100) NOT NULL,
DEPOCINSI char(1),
BLOKESIRASI int NOT NULL
);
CREATE UNIQUE INDEX XUTDEPOTURP ON TDEPOTUR(ID);
Any ideas on what I should do?
Your property definition with the FK is wrong, as i saw you use updatable, insertable to false, you what really want is that the FK object is not modified because could be a master table common for some other entities.
Then what you can use is this
#ManyToOne(cascade= {CascadeType.DETACH})
#JoinColumn(name = "DEPOTUR")
#NotNull
private DepoTur depoTur;
With DETACH, you will save the value only in the first table, column DEPOTUR and wont update the object in the DepoTur table
Also add the FK in your first table
CREATE TABLE TDEPOFAZLA
(
ID decimal(20,0) PRIMARY KEY NOT NULL,
GRUP int NOT NULL,
DEPOTUR decimal(20,0) NOT NULL,
FAZLABULUNDURMAORANI decimal(6,2) NOT NULL
);
CREATE UNIQUE INDEX XUTDEPOFAZLAP ON TDEPOFAZLA(ID);
CONSTRAINT fk_column FOREIGN KEY (DEPOTUR) REFERENCES TDEPOTUR(ID);
The problem was that I didn't reference the join column properly. This solved the problem:
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "DEPOTUR", referencedColumnName = "ID", nullable = false, columnDefinition = "DECIMAL(20,0)")
#NotNull
private DepoTur depoTur;
It appears that you specified the same name for the join column Id twice in your DepoFazla model you have to change its name use for example :
#Entity
#Table(schema = "PGMTEMS", name = "TDEPOFAZLA")
public class DepoFazla implements Serializable {
private static final long serialVersionUID = -2800365387332643658L;
...
#ManyToOne(fetch = FetchType.LAZY, targetEntity = DepoTur.class)
#JoinColumn(name = "ID_depoTur", insertable = false, updatable = false)
#NotNull
private DepoTur depoTur;
...
}

Categories