'default' is not working in #Column in Spring Boot - spring

Below is my entity class, I have added default contraint on my EnumType variable of class. But while the value in the db, it not taking that value and giving ContraintViolation.
Entity
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "employee")
public class Employee{
#Id
private String id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "email", nullable = false)
private String email;
#Column(name = "language", nullable = false, columnDefinition = "VARCHAR(10) default 'ENGLISH'")
#Enumerated(EnumType.STRING)
private Language language;
}
Here, if I remove nullable from Language Enum, the language is saved as null. Why is it not taking default value as ENGLISH

Since Language is of type ENUM, you can use:
#Column(name = "language", nullable = false, columnDefinition = "enum('ENGLISH' , 'CHINESE') default 'ENGLISH'")

How about initializing your enum property with default value like below?
#Column(name = "language", nullable = false, columnDefinition = "VARCHAR(10) default 'ENGLISH'")
#Enumerated(EnumType.STRING)
private Language language = Language.ENGLISH;
Refer this answer for more details

Related

JPA Hibernate Problem for One to One Relationship with Embedded ID

I am struggling with the following problem that I've been trying to solve. After checking solutions on StackOverflow and articles on Baeldung I still get different JPA errors when trying to map the following ONE-TO-ONE relationship between 2 Oracle SQL tables with composite PK in a SpringBoot application:
MASTER
ID
VERSION
1
2022.1
Constraint:
PK_MASTER PRIMARY KEY(ID, VERSION)
MASTER_DETAILS
MASTER_ID
VERSION
DETAILS
1
2022.1
details
Constraint:
PK_MASTER_DETAILS PRIMARY KEY(MASTER_ID, VERSION)
FK_MASTER_DETAILS FOREIGN KEY(MASTER_ID, VERSION) REFERENCES MASTER(ID, VERSION)
After some failures in trying to map it using the #OneToOne JPA annotation with both classes having #EmbeddedId set on the composite PK, I also installed JPA Buddy to check how it will be generated and that resulted in the following 4 classes:
Master.java
#Getter
#Setter
#Entity
#Table(name = "master")
public class Master {
#EmbeddedId
private MasterId id;
#OneToOne(mappedBy = "master")
private MasterDetails masterDetails;
}
MasterId.java
#Getter
#Setter
#Embeddable
public class MasterId implements Serializable {
private static final long serialVersionUID = 8254837075462858051L;
#Column(name = "id", nullable = false)
private BigDecimal id;
#Lob
#Column(name = "version", nullable = false)
private String version;
}
MasterDetails.java
#Getter
#Setter
#Entity
#Table(name = "master_details")
public class MasterDetails {
#EmbeddedId
private MasterDetailsId id;
#MapsId
#OneToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumns({
#JoinColumn(name = "master_id", referencedColumnName = "id", nullable = false),
#JoinColumn(name = "version", referencedColumnName = "version", nullable = false)
})
private Master master;
#Lob
#Column(name = "details", nullable = false)
private String details;
}
MasterDetailsId.java
#Getter
#Setter
#Embeddable
public class MasterDetailsId implements Serializable {
private static final long serialVersionUID = -8375336118866998644L;
#Column(name = "master_id", nullable = false)
private BigDecimal masterId;
#Lob
#Column(name = "version", nullable = false)
private String version;
}
When running the SpringBoot application with this JPA structure the run time error received is:
org.hibernate.PropertyNotFoundException: Could not locate field [id] on class [org.project.packages.MasterDetails]
After removing the #MapsId that cause this error the application starts but when trying to insert data in the tables I get the following error:
org.hibernate.id.IdentifierGenerationException: null id generated for:class org.project.packages.MasterDetails
Checking in the H2 test database I noticed that the FK on the Master_Details table was not present, but only the PK was set.
I would appreciate any help in pointing out how this problem can be solved: other annotations required (Cascade/FetchType) or in case there are any changes to be made to the database level (I also tried adding a separate identifier column in the Master_Details table defined as PK and only keep the FK to the Master table). Thanks in advance!
After many tries, I figured out to solve the issue.
I had to use a common key between the two entities and also FetchType.LAZY.
MasterDetails.class
public class MasterDetails {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name="ID", column=#Column(name="MASTER_ID"))
})
private MasterId id;
#OneToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumns({
#JoinColumn(name = "master_id", referencedColumnName = "id", nullable = false),
#JoinColumn(name = "version", referencedColumnName = "version", nullable = false)
})
private Master master;
#Lob
#Column(name = "guidance", nullable = false)
private String guidance;
}
Master.class
public class MasterSheet {
#EmbeddedId
private MasterId id;
#OneToOne(mappedBy = "master", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private MasterDetails masterDetails;
}

JPA Repository.findByKeyEquals() returns not present value, but the value is exist on db

I'm developing an application that queries a database.
There are a few issues right now.
history.isPresent() == false when calling Optional<History> findByKeyEquals() intermittently. but value is exist on database
This is the information I got while tracking the issue.
All child entities are non-null.
In most cases, if the same function is re-executed, it is searched.
But sometimes it doesn't happen intermittently.
i think that i use incorrectly table relationship annotation (#OneToMany,#ManyToOne options..)
I want to solve this issue.
this is my code
History (Parent)
#Table(
indexes = {
#Index(columnList = "key", unique = true),
})
#Entity
#Getter
#ToString
#Audited
public class History implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(updatable = false, nullable = false, columnDefinition = "BIGINT UNSIGNED")
private Long id;
#Setter
#Column(nullable = false, columnDefinition = "CHAR(36)")
private String key = UUID.randomUUID().toString();
#Setter
#Temporal(TemporalType.TIMESTAMP)
#NotAudited
private Date started = new Date();
#Setter
#Temporal(TemporalType.TIMESTAMP)
#NotAudited
private Date finished;
#Setter
#OneToMany(
cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
mappedBy = "history",
orphanRemoval = true)
#NotAudited
private List<Content> contents = new ArrayList<>();
...
}
Content (Child)
#Table
#Entity
#Getter
#Audited
public class Content implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(updatable = false, nullable = false, columnDefinition = "BIGINT UNSIGNED")
private Long id;
#Setter
#Column(columnDefinition = "LONGTEXT")
#NotAudited
private String content;
#Setter
#ManyToOne(targetEntity = History.class, fetch = FetchType.Lazy, optional = false)
#Audited
private History history;
...
}
Repository
public interface HistoryRepository
extends JpaRepository<History, Long>, RevisionRepository<History, Long, Integer> {
Optional<History> findByKeyEquals(final String key);
}

How to write custom findAll() with Specification in JPA repository

When I use skuRepository.getAll(), it works OK, but when I apply filters, defined in Specification (List filteredRegs = skuRepository.getAll(specification)) I still get all the rows of the table
What should i do to apply the specifications to my custom method?
public interface SkuRepository extends CrudRepository<Sku, Integer>, JpaSpecificationExecutor<Sku> {
#Query("select s from Sku s join fetch s.unit un join fetch s.supplier sup WHERE un.id = sku_unit_id AND sup.id = supplier_id")
List<Sku> getAll(#Nullable Specification<Sku> var1);
#Query("select s from Sku s join fetch s.unit un join fetch s.supplier sup WHERE un.id = sku_unit_id AND sup.id = supplier_id")
List<Sku> getAll();
}
UPD:
Here is my entities.
When I make sampling by a Sku table using the Specification API, I see three separate selects in log: one for Sku entity, one for Unit and one for Suppliers. I want my app to make one select with joins.
I read that this is due to the fact that I use EAGER fetch type, so I change it to LAZY, but then I got another problem: "InvalidDefinitionException: No serializer found..." This is logical because related entities Unit and Supplier are not loaded.
Then I decided to write my custom getAll() with request:
#Query("select s from Sku s join fetch s.unit un join fetch s.supplier sup WHERE un.id = sku_unit_id AND sup.id = supplier_id ORDER BY s.name")
But now it does not support Specification.
Please advise what to do.
#Entity
#Table(name = "sku")
public class Sku implements Cloneable, CloneableEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "sku_code", length = 6, nullable = false, unique = true)
private String code;
#Column(name = "sku_name", nullable = false)
private String name;
#ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
#JoinColumn(name = "sku_unit_id", nullable = false)
private Unit unit;
#ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
#JoinColumn(name = "supplier_id", nullable = false)
private Supplier supplier;
#Column(name = "qty_in_sec_pkg")
private int quantityInSecondaryPackaging;
#Column(name = "sku_is_active", nullable = false)
private boolean isActive;
//constructors, getters, setters
}
#Entity
#Table(name = "units")
public class Unit {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id ")
private int id;
#Column(name = "unit", nullable = false, unique = true)
private String unit;
#Column(name = "description")
private String description;
//constructors, getters, setters
}
#Entity
#Table(name = "suppliers")
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id ")
private int id;
#Column(name = "supplier_code", length = 6, nullable = false, unique = true)
private String supplierCode;
#Column(name = "supplier_name", nullable = false)
private String name;
#Column(name = "create_date", length = 19, nullable = false)
private String createDate;
#Column(name = "update_date", length = 19)
private String updateDate;
//constructors, getters, setters
}
You can't mix #Query and Specification
You can only use JpaSpecificationExecutor interface methods to use Specification.
Find more details here

Is there any way to delete entities from child entity using JPA?

I have 3 tables Table A, B, C. Table A is associated #OneToMany with Table B. Table B is associated #ManyToOne with Table C. Now when I find by Id of Table A, I am able to get details of A,B,C. But when I persist / delete, It is affecting only Table A&B. Table C is unaffected.
Is this possible in JPA to delete entities from child entity? Googled lot, but could not find any clue.
Below are the entity models of all the three tables
#Entity
#Table(name = "FEATUREMASTER")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class FeatureMaster implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "FGID")
private String featureid;
#Column(name = "FEATURENAME", nullable = false, unique = false)
private String featurename;
#Column(name = "DESCRIPTION", nullable = true, unique = false)
private String description;
#Column(name = "LIBNAME", nullable = true, unique = false)
private String libname;
#Column(name = "ISENABLED", nullable = false, unique = false)
private String isenabled;
#Column(name = "EDRULEGRP", nullable = true, unique = false)
private String edrulegrp;
// Do Not use - [orphanRemoval = true & CascadeType.ALL]- If used, deletion is not happening
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinColumn(name = "FGID")
private List<CfgMaster> parameters;
// Getters and Setters
}
#Entity
#Table(name = "CFGMASTER")
public class CfgMaster implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#EmbeddedId
private CfgMasterPK id;
#Column(name = "CONFIGNAME", length = 45, nullable = true, unique = false)
private String parameter_name;
#Column(name = "CONFIGTYPE", length = 20, nullable = true, unique = false)
private String type;
#Column(name = "SUBPARAM", nullable = true, unique = false)
private Integer subparam;
#Column(name = "CONFIGDESCRIPTION", nullable = true, unique = false)
private String description;
#Column(name = "CONFIGLIMITFROM", nullable = true, unique = false)
private String from;
#Column(name = "CONFIGLIMITTO", nullable = true, unique = false)
private String to;
#ManyToOne(cascade = {CascadeType.ALL}, optional = true, fetch = FetchType.LAZY )
// #ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
#NotFound(action=NotFoundAction.IGNORE) // This is required to handle when no CfgData is found
#JoinColumns({
#JoinColumn(name = "FGID", insertable = false, updatable = false),
#JoinColumn(name = "DATAKEY", insertable = false, updatable = false)
})
private CfgData cfgData;
//Getters and Setters
}
#Entity
#Table(name = "CFGDATA")
public class CfgData implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/*#EmbeddedId
private CfgDataPK id;*/
#Id
#Column(name = "FGID")
private String fgid;
#Id
#Column(name = "DATAKEY")
private String datakey;
#Column(name = "EPID", nullable = false, unique = false)
private int epid;
#Column(name = "RESERVED1", length = 45, nullable = true, unique = false)
private String reserved1;
#Column(name = "VALUE1", length = 100, nullable = true, unique = false)
private String value1;
#Column(name = "VALUE2", length = 100, nullable = true, unique = false)
private String value2;
//Getters and Setters
}
The problem I am facing is, I am not able to delete/save the entities of CfgData by passing FeatureMaster's primary id. Any operation I do is affecting only parent &child, not the grand child (CfgData) I tried a lot googling, but I cant find the solution.

Mapping of oneToMany with composite key using eclipselink gives me ORA-01400

I am trying to map the classic bi-directional oneToMany using eclipselink.
My problem is that when i want to insert a new 'child' i get
SQLIntegrityConstraintViolationException.
The database is described like this :
#Entity
#IdClass(KuponPK.class)
#Table(name = "KUPON", schema = "POST", catalog = "")
public class Kupon implements Serializable {
private Integer id;
private String spil;
private Collection<Kombination> kombinationList;
#OneToMany(mappedBy = "kupon", cascade = CascadeType.PERSIST)
public Collection<Kombination> getKombinationList() {
return kombinationList;
}
public class KuponPK implements Serializable {
private Integer id;
private String spil;
#Id
#Column(name = "ID", nullable = false, insertable = true, updatable = true, precision = 0)
public Integer getId() {
return id;
}
#Id
#Column(name = "SPIL", nullable = false, insertable = true, updatable = true, length = 5)
public String getSpil() {
return spil;
}
#Entity
#Table(name = "KOMBINATION", schema = "POST", catalog = "")
public class Kombination {
private Integer id;
private String sorteringOrden;
private Integer sorteringNr;
private Integer antalSpillede;
private BigDecimal odds;
private Kupon kupon;
#ManyToOne
#JoinColumns({#JoinColumn(name = "KUPON_ID", referencedColumnName = "ID", nullable = false, insertable=false, updatable=false),
#JoinColumn(name = "KUPON_SPIL", referencedColumnName = "SPIL", nullable = false, insertable=false, updatable=false)})
public Kupon getKupon() {
return kupon;
}
In my stateless session i have a Kupon object and i create a new Kombination where i set the Kupon and try to merge, but im getting
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("KOMBINATION"."KUPON_ID")
which is obvious since its part of primary key
I am setting the Kombination to Kupon and the Kupon to Kombination, but that doesnt make any difference
How can can i tell that the key is inside the Kupon object which im setting in the Kombination object ??

Resources