Play Framework 2 Ebean specify default value for field - java

I have a simple model in Play Framework 2, and I would like to specify a default value to be inserted on a specify INT column if none is provided when the INSERT is performed.
Model:
#Entity
#Table(name = "DashboardOptions", schema = "dbo")
public class DashboardOptions extends Model implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
public Long id;
#Basic(optional = false)
#Column(name = "userId")
public Long userId;
#Column(name = "chartType")
public String chartType;
public String name;
public Integer size = 2;
I'd like to have the size column populate with 2 by default, however, if I specify the default value as above, my database evolution does not reflect this:
create table dbo.DashboardOptions (
id numeric(19) identity(1,1) not null,
userId numeric(19) not null,
chartType varchar(255),
name varchar(255),
size integer,
constraint pk_DashboardOptions primary key (id))
;
What I would expect to see is this:
create table dbo.DashboardOptions (
id numeric(19) identity(1,1) not null,
userId numeric(19) not null,
chartType varchar(255),
name varchar(255),
size integer default 2,
constraint pk_DashboardOptions primary key (id))
;

Use own columnDefinition like this:
#Column(columnDefinition = "integer default 2")
public Integer size = 2;

Another option is to use #PrePersist tag package javax.persistence. you can have a method decorated in your bean with #PrePersist and that method is called before Ebean.save call. so in this case the following code would set the default value of size to 2.
#PrePersist
protected void onCreate {
if (this.size == null)
this.size = 2;
}
This approach is applicable only within the context of ORM (Ebean) and obviously wouldn't work directly with SQL. The advantage of this method is that this is more database neutral in the sense that integer default 2 might not be a valid column definition string in some unknown strange RDBMS systems.

Related

Hibernate is not mapping object correctly ("Bad value for type" exception) when using compound primary keys in a junction table

I am getting the exception o.h.e.j.s.SqlExceptionHelper | Bad value for type int : 9dac4fd2-a04c-4be7-976b-d880a43ea25a. It seems to want to put a UUID in an Integer field here.
I have the following tables, which admittedly are a bit complex in terms of compound keys:
CREATE TABLE public.event (
id uuid NOT NULL,
...
CONSTRAINT event_pkey PRIMARY KEY (id)
);
CREATE TABLE public.condition_set (
api_id uuid NOT NULL,
version integer NOT NULL,
...,
CONSTRAINT condition_set_pkey PRIMARY KEY (api_id, version)
);
CREATE TABLE public.condition_set_event (
condition_set_api_id uuid NOT NULL,
condition_set_version integer NOT NULL,
event_id uuid NOT NULL,
CONSTRAINT condition_set_event_pkey PRIMARY KEY (condition_set_api_id, condition_set_version, event_id),
CONSTRAINT fk_condition_set FOREIGN KEY (condition_set_api_id, condition_set_version) REFERENCES public.condition_set(api_id, version) ON DELETE CASCADE,
CONSTRAINT fk_event FOREIGN KEY (event_id) REFERENCES public.event(id) ON DELETE CASCADE
);
In my model I have the Event class which is fairly straightforward. The ConditionSet class has a compound primary key matching the database structure, as follows:
#Entity
public class ConditionSet {
#EmbeddedId
private ConditionSetId id;
}
which looks like:
#Embeddable
public class ConditionSetId implements Serializable {
private static final long serialVersionUID = 8110138933878596476L;
private UUID apiId;
private Integer version;
}
The tricky part is the ConditionSetEvent junction table which ALSO consists of a compound key, of which one is the compound key of ConditionSet
#Entity
public class ConditionSetEvent {
#EmbeddedId
private ConditionSetEventId id;
#ManyToOne(fetch = FetchType.LAZY)
#OnDelete(action = OnDeleteAction.CASCADE)
#MapsId("conditionSetId")
#JoinColumns(foreignKey = #ForeignKey(name = "fk_condition_set"), value = {
#JoinColumn(nullable = false, name = "conditionSetApiId"),
#JoinColumn(nullable = false, name = "conditionSetVersion")
})
private ConditionSet conditionSet;
#ManyToOne(fetch = FetchType.LAZY)
#OnDelete(action = OnDeleteAction.CASCADE)
#MapsId("eventId")
#JoinColumn(foreignKey = #ForeignKey(name = "fk_event"))
private Event event;
public ConditionSetEvent(ConditionSet conditionSet, Event event) {
this.conditionSet = conditionSet;
this.event = event;
this.id = new ConditionSetEventId(conditionSet.getId(), event.getId());
}
}
with its EmbeddedId:
#Embeddable
public class ConditionSetEventId implements Serializable {
private static final long serialVersionUID = -6269791751266804667L;
private ConditionSetId conditionSetId;
private UUID eventId;
}
However, if I try to query this junction table with this repository method:
public interface ConditionSetEventRepository extends JpaRepository<ConditionSetEvent, ConditionSetEventId> {
#Query("select cse from ConditionSetEvent cse where cse.id.eventId = :eventId")
List<ConditionSetEvent> findByEventId(UUID eventId);
}
then I get the error as mentioned on top (where the uuid in the exception is a valid ConditionSet.apiId, but that somehow seems to be re-used.
With trace logging:
DEBUG | org.hibernate.SQL | select conditions0_.condition_set_api_id as conditio0_8_, conditions0_.event_id as event_id1_8_, conditions0_.condition_set_api_id as conditio2_8_, conditions0_.condition_set_version as conditio3_8_ from condition_set_event conditions0_ where conditions0_.event_id=?
TRACE | o.h.t.d.sql.BasicBinder | binding parameter [1] as [OTHER] - [be1ec45d-6533-4e77-98b7-f9a357cda052]
TRACE | o.h.t.d.s.BasicExtractor | extracted value ([conditio0_8_] : [OTHER]) - [9dac4fd2-a04c-4be7-976b-d880a43ea25a]
WARN | o.h.e.j.s.SqlExceptionHelper | SQL Error: 0, SQLState: 22003
ERROR | o.h.e.j.s.SqlExceptionHelper | Bad value for type int : 9dac4fd2-a04c-4be7-976b-d880a43ea25a
So it does manage to extract that UUID value initially (the last trace line), but on the next step (for the Integer) it still is trying to use the UUID instead of the Integer.
Am I doing something wrong here?
I don't think you need the #JoinColumns and it is messing up which id column maps to which id field in ConditionSetEventId
#Entity
public class ConditionSetEvent {
#EmbeddedId
private ConditionSetEventId id;
#ManyToOne(fetch = FetchType.LAZY)
#OnDelete(action = OnDeleteAction.CASCADE)
#MapsId("conditionSetId")
private ConditionSet conditionSet;
....

How to implement Composite Primary key and Composite Foreign Key using JPA,Hibernate, Springboot

I searched a lot for this particular problem but i didn''t find any specific solution. I have a Composite Primary Key in one table and one of the field from this composite primary key is the part of the Composite Primary Key of another table. You can say that this particular field is the foreign key in the second table but i a not defining any exclusive Foreign Key constraint in the table definition. There can be multiple Records in the second table for each rec in the first table.i am trying to implement this using SPringBoot-JPA-Hibernate but not being able to do so. Can some body help me here. Here are the detais:-
I have a USER_CREDENTIAL table with following fields:-
CREATE TABLE `INSTITUTION_USER_CREDENTIAL` (
`INSTITUTION_USER_ID INT(10) NOT NULL, -> AutoGeneratd
`INSTITUTION_USER_NAME` VARCHAR(50) NOT NULL,
`INSTITUTION_USER_PASSWORD` VARCHAR(50) NOT NULL,
`FIRST_NAME` VARCHAR(100) NOT NULL,
`MIDDLE_NAME` VARCHAR(100),
`LAST_NAME` VARCHAR(100) NOT NULL,
PRIMARY KEY (`INSTITUTION_USER_ID`,`INSTITUTION_USER_NAME`)
);
2) Here is my second table
CREATE TABLE `INSTITUTION_USER_CREDENTIAL_MASTER` (
`INSTITUTION_ID` INT(10) NOT NULL, -> Autogenerated
`INSTITUTION_USER_ID` INT(10) NOT NULL, -> Coming from
INSTITUTION_USER_CREDENTIAL
`INSTITUTION_USER_ROLE` CHAR(02) NOT NULL,
`INSTITUTION_USER_STATUS` CHAR(02) NOT NULL,
`INSTITUTION_NAME` VARCHAR(200) NOT NULL,
`LAST_UPDT_ID` VARCHAR(100) NOT NULL,
`LAST_UPDT_TS` DATETIME NOT NULL,
PRIMARY KEY(`INSTITUTION_ID`,`INSTITUTION_USER_ID`,`INSTITUTION_USER_ROLE`)
);
Note that i haven't declare any particular foreign key in the second table. I have two #Embeddable Class corresponding to two primary key structure for two different table:-
For the INSTITUTION_USER_CREDENTIAL table:-
#Embeddable
public class InstitutionUserCredentialPrimaryKey implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name = "INSTITUTION_USER_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int institutionUserId;
#Column(name = "INSTITUTION_USER_NAME")
private String institutionUserName;
//Getter-Setters removed for clarity
}
Corresponding Entity Class:-
#Entity(name = "INSTITUTION_USER_CREDENTIAL")
public class InstitutionUserCredential {
#EmbeddedId
private InstitutionUserCredentialPrimaryKey
institutionUserCredentialPrimaryKey;
#Column(name = "INSTITUTION_USER_PASSWORD")
private String instituteUserPassword;
#Column(name = "FIRST_NAME")
private String firstname;
#Column(name = "MIDDLE_NAME")
private String middleName;
#Column(name = "LAST_NAME")
private String lastName;
#OneToMany(mappedBy="institutionUserCredential", cascade = CascadeType.ALL)
private List<InstitutionUserCredentialMaster>
institutionUserCredentialMaster;
//Getter-Setter and other part of the code removed for clarity
}
For the INSTITUTION_USER_CREDENTIAL_MASTER table:-
#Embeddable
public class InstituteUserCredentialMasterPrimaryKey implements Serializable
{
private static final long serialVersionUID = 1L;
#Column(name = "INSTITUTION_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int institutionId;
#Column(name = "INSTITUTION_USER_ID")
private int institutionUserId;
#Column(name = "INSTITUTION_USER_ROLE")
private String userRole;
//Getter-Setter and other part of the code removed for clarity
}
Entity Class:-
#Entity(name = "INSTITUTION_USER_CREDENTIAL_MASTER")
public class InstitutionUserCredentialMaster {
#EmbeddedId
private InstituteUserCredentialMasterPrimaryKey
instituteUserCredentialMasterPrimaryKey;
#Column(name = "INSTITUTION_USER_STATUS")
private String userStatus;
#Column(name = "INSTITUTION_NAME")
private String institutionName;
#Column(name = "LAST_UPDT_ID")
private String lastUpdateId;
#Column(name = "LAST_UPDT_TS")
private String lastUpdateTimestamp;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="institutionUserId", referencedColumnName =
"INSTITUTION_USER_ID")
})
private InstitutionUserCredential institutionUserCredential;
//Getter-Setter and other part of the code removed for clarity
}
Note that only 1 field INSTITUTION_USER_ID, is getting used in the Composite PrimaryKey of the InstitutionUserCredentialMaster and is coming from the composite primary key of the InstitutionUserCredential.
When i am running my code this is giving me an error like :-
Invocation of init method failed; nested exception is
org.hibernate.AnnotationException:
referencedColumnNames(INSTITUTION_USER_ID) of com.bnl.application.entity.InstitutionUserCredentialMaster.institutionUserCredential referencing com.bnl.application.entity.InstitutionUserCredential not mapped to a single property
None of the examples i have seen so far involving the Composite Primary key and foreign key doesn't treat any one particular field and is more of the entire key structure. I am using MYSQL and i have checked that we can create table having composite primary key and one of the field from that composite key is foreign key in another table and also part of the Composite Primary key of the second table.
Any pointers appreciated
UPDATE:- In my first post i made a mistake while posting it. I am sorry that institutionUserName became a part of the InstitutionUserCredentialMaster. it was a typo. There is no existence of the intitutionUserName in the InstitutionUserCredentialMaster table. i have fixed that and updated the post.
***** Update based on the input by Niver and Wega *****
Update to the InstitutionUserCredentialMasterPrimaryKey
#Embeddable
public class InstituteUserCredentialMasterPrimaryKey implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "INSTITUTION_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int institutionId;
#Column(name = "INSTITUTION_USER_ID")
private int institutionUserId;
// Added the institutionUserName
#Column(name = "INSTITUTION_USER_NAME")
private String institutionUserName;
#Column(name = "INSTITUTION_USER_ROLE")
private String userRole;
}
Update to the Entity Class InsstitutionUserCredentialMaster :-
#Entity(name = "INSTITUTION_USER_CREDENTIAL_MASTER")
public class InstitutionUserCredentialMaster {
#EmbeddedId
private InstituteUserCredentialMasterPrimaryKey instituteUserCredentialMasterPrimaryKey;
#Column(name = "INSTITUTION_USER_STATUS")
private String userStatus;
#Column(name = "INSTITUTION_NAME")
private String institutionName;
#Column(name = "LAST_UPDT_ID")
private String lastUpdateId;
#Column(name = "LAST_UPDT_TS")
private String lastUpdateTimestamp;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="institutionUserId", referencedColumnName = "INSTITUTION_USER_ID"),
#JoinColumn(name="institutionUserName",referencedColumnName = "INSTITUTION_USER_NAME")
})
private InstitutionUserCredential institutionUserCredential;
}
This time i am getting an error like
Invocation of init method failed; nested exception is org.hibernate.DuplicateMappingException: Table [institution_user_credential_master] contains physical column name [institution_user_id] referred to by multiple physical column names: [institutionUserId], [INSTITUTION_USER_ID]
I think that the problem is that you are not referencing the other part of the EmbeddedId in the JoinColumns annotation. You have defined that also the institutionUserName is part of the primary key, so you should mention it as well in the definition of the foreign key in entity InstitutionUserCredentialMaster.

Hibernate Postgresql boolean problems

I have object with boolean field like
#Entity
#Table(name = "USERS")
public class User {
#Id
#GeneratedValue
#Column(name = "ID")
private Integer id;
#Column(name = "ACTIVE")
private Boolean active = true;
}
AND query for creating
CREATE TABLE IF NOT EXISTS USERS(
ID SERIAL PRIMARY KEY,
ACTIVE SMALLINT ,
LOGIN CHAR(255) NOT NULL,
NAME CHAR(255) NOT NULL,
PASSWORD CHAR(255) NOT NULL,
ROLE INTEGER NOT NULL REFERENCES ROLE(ID)
);
When i try to take a user object i have next exception ERROR: operator does not exist: smallint = boolean
In PostgreSQL, SMALLINT maps to Short and BOOLEAN maps to Boolean (hence the name).
You get to decide whether to change the class or the table.
try adding :
#Type(type = "org.hibernate.type.NumericBooleanType")

jpa / hibernate how to map element collection by foreign key with annotations

Given these two tables:
CREATE TABLE `soc` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32),
PRIMARY KEY (`id`));
CREATE TABLE `soc_attitude` (
`soc_id` INT NOT NULL,
`target_soc_id` INT NOT NULL,
`attitude` INT,
PRIMARY KEY (`soc_id`,`target_soc_id`));
In the Soc class, I want to get all rows matching this.soc_id from the soc_attitude table using a field like this:
private Map<Integer,Integer> attitudes;
Where the key of the map is target_soc_id and the value is attitude.
I got as far as this:
#Entity
#Table(name = "soc")
public class Soc {
#Id
#Column( name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name="name")
private String name;
#ElementCollection
#CollectionTable(name="soc_attitude",joinColumns=#JoinColumn(name="soc_id"))
#Column(name="attitude")
private Map<Integer,Integer> attitudes;
But I think this will make soc_id the key and attitude the value.
What annotations do I use? (using Hibernate 4.3.11.Final)
Use #MapKeyColumn
Try this:
#ElementCollection
#CollectionTable(name="soc_attitude",joinColumns=#JoinColumn(name="soc_id"))
#Column(name="attitude")
#MapKeyColumn(name="target_soc_id")
private Map<Integer,Integer> attitudes;

Trouble with a mapped class (OneToMany) containing OneToOne mappings

I have been trying to map some "OneToOne" relationships between two users via an intermediate class called Guardian. When i try to retrieve a user (and his guardians) i get an internal server error in return from Glassfish (Open edition v4.0). There is however no stack trace of any kind or any error displayed in the logs. I suspect that the issue is my mapping within the JPA classes.
Starting the server i get two warnings related to the Guardian class which I don't really understand:
WARNING: The reference column name [GUARDIAN] mapped on the element [method getGuardianUserBean] does not correspond to a valid id or basic field/column on the mapping reference. Will use referenced column name as provided.
WARNING: The reference column name [OWNER] mapped on the element [method getOwnerUserBean] does not correspond to a valid id or basic field/column on the mapping reference. Will use referenced column name as provided.
SQL create statements:
create table HOMEFREE."user" (
userid integer GENERATED ALWAYS AS IDENTITY,
name varchar(255) not null,
displayname varchar(255) unique not null,
password varchar(255) not null,
tlf integer,
facebookID varchar(255),
googleid varchar(255),
authtoken varchar(255),
email varchar(255) unique not null,
primary key(userid)
);
create table HOMEFREE."guardian" (
guardianId integer GENERATED ALWAYS AS IDENTITY,
owner integer not null,
guardian integer not null,
confirmed boolean not null,
primary key(guardianId),
foreign key(owner) references homeFree."user"(userid),
foreign key(guardian) references homeFree."user"(userid)
);
Relevant fields/annotations in entity classes:
#Entity
#Table(name = "\"user\"", schema = "HOMEFREE")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int userId;
#OneToMany(mappedBy = "ownerUserBean", fetch = FetchType.EAGER)
private List<Guardian> guardians;
}
#Entity
#Table(name="\"guardian\"", schema="HOMEFREE")
public class Guardian implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int guardianId;
#OneToOne
#PrimaryKeyJoinColumn(name="OWNER", referencedColumnName="USERID")
private User ownerUserBean;
#OneToOne
#PrimaryKeyJoinColumn(name="GUARDIAN", referencedColumnName="USERID")
private User guardianUserBean;
private boolean confirmed;
}
Try using #JoinColumn instead of #PrimaryKeyJoinColumn.
#OneToOne
#JoinColumn(name="OWNER", referencedColumnName="USERID")
private User ownerUserBean;
#OneToOne
#JoinColumn(name="GUARDIAN", referencedColumnName="USERID")
private User guardianUserBean;
According to spec the latter should be used to join the primary table of an entity subclass in the JOINED mapping strategy to the primary table of its superclass (exact definition available here)

Categories