Default Column value is not working in hibernate - java

I set "firm_name" default value in Ben using annotation.
But when I insert data it will add NULL in database.
I want to set default value into database so that I just set the values which are require.
Other column values set as default value which is set into Bean.
Following is my Code.But it is not working. I will inset nNULL value into database.
#Entity
#Table(name = "my_leads")
public class My_leads{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id")
int id;
#Column(name = "name", length = 100,columnDefinition = "varchar(255) default 'NA'")
String name;
#Column(name = "enrtyDate", insertable = false, updatable = false, nullable = false,columnDefinition = "datetime default NOW()")
Date enrtyDate;
#Column(name = "mobileNo", nullable = false, length = 100)
String mobileNo;
#Column(name = "firm_name", length = 100, nullable = false,columnDefinition = "varchar(255) default 'No Refrence'")
String firm_name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getEnrtyDate() {
return enrtyDate;
}
public void setEnrtyDate(Date enrtyDate) {
this.enrtyDate = enrtyDate;
}
public String getMobileNo() {
return mobileNo;
}
public void setMobileNo(String mobileNo) {
this.mobileNo = mobileNo;
}
public String getFirm_name() {
return firm_name;
}
public void setFirm_name(String firm_name) {
this.firm_name = firm_name;
}
}
My_Leads lead=new My_Leads();
lead.setUser(1);
lead.setMobileNo("1234567896");
lead.setName("Sajan");
lead.setPriority(1);
lead.setStage(1);
lead.setCampain(1);
adminService.SaveLead(lead)

The code you wrote is not a way to set a default value by Hibernate - it's actually for a database.
When you create a table in the database you can define a column such way that if you try inserting a null value the default value will be inserted instead. That's what you did here varchar(255) default 'No Refrence'.
If your table is already created, Hibernate is gonna ignore that statement. That statement is used only when Hibernate is creating the schema for you, using #Entity classes. If you go into your database and check column definitions you will see that your column has no default value, since it was not created by Hibernate.
You can delete your schema and let Hibernate create it for you, then the default value will work. Or you can edit your schema manually, adding default value to already existing column. For example:
ALTER TABLE my_leads ALTER COLUMN firm_name SET DEFAULT 'No Refrence'
If you let Hibernate generate your schema and still have this error - make sure those are actually null values, not NULL strings or something.
If you don't want to have the default values inserted by database, but by Hibernate, do this in your #Entity class:
String firm_name = "No Refrence";

Whenever an entity is to be inserted, Hibernate is going to generate the following DML:
INSERT
INTO my_leads (id, name, enrtyDate, mobilNo, firm_name)
VALUES (?, ?, ?, ?, ?)
In your java code, you're simply not setting a value for firm_name so that property is null.
Whether or not the default value for the column is used is going to depend upon what database platform you're using and how it interprets NULL in this case.
For example, MySQL will see that Hibernate bound NULL for the firm_name and will therefore apply the default value for you rather than setting the column as NULL.
For example, SQL Server will see that the INSERT statement contains the field firm_name in the columns section and therefore will ignore the default value and use whatever value is supplied in the values section, thus the column will be set to NULL. The only way SQL Server will use the default value is if the column is omitted from the columns section of the insert statement.
The only way to guarantee that the default value is set regardless of your database platform is to make sure that your entity state adheres to that rule too. This means you either need to initialize firm_name with the default value in the field definition, in the constructor of your class or your business logic that constructs your entities.

Related

JPA Annotation #Column(insertable=false) is being ignored, why?

I want one of the fields to be ignored when called save() method. The field is gonna get populated automatically by the database and returned. It should be treated as a read-only field.
I am concerned about private Timestamp ts; field:
#Entity
#Table(name = "time_series", schema = "ms")
#IdClass(Reading.class)
public class Reading implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "name", nullable = false)
private String sensorName;
#Id
#Column(name = "ts", insertable = false, updatable = false)
private Timestamp ts;
#Column(name = "reading")
private Double value;
...
As you see, I use insertable = false, updatable = false are inside the #Column annotation, so I'd expect that ts is ignored when forming the actual SQL behind the curtain.
#Override
#Transactional(readOnly = false)
public Reading save(Reading r) {
return readingRepository.save(r);
}
ReadingRepository is basically extended Spring's CrudRepository which has save(...) method.
When I save Reading object with ts=null I get an error from Postgres:
ERROR: null value in column "ts" violates not-null constraint
because Spring Data did not actually ignore the ts field based what I see from the log:
insert into ms.time_series (ts, name, reading) values (NULL, 'sensor1', 10.0)
Clearly, I want the query to be without ts like this:
insert into ms.time_series (name, reading) values ('sensor1', 10.0)
Why is the field not being ignored?
Now if you ask me whether my database schema is okay I say yes. When I type SQL query in console without the ts everything is fine. I even tried #Generated and #GeneratedValue annotations. Name and ts are both forming a primary key for the table, however, the result is the same if I make only one of them a PK or if I add an extra surrogate ID column. Same result...
Am I overlooking something or is there maybe a bug in the Spring framework?? I am using Spring 5.1.2 and SpringData 2.1.2
Note: If I use #Transient annotation that persists the insert query correctly but then the field is being ignored completely even on read/fetch.
Many thanks for any help with this!
Try using GenericGenerator and GeneratedValue in your code.
Add the needed annotation and give values to all other members in Reading class, except ts.
Here some examples.
As you say
I get an error from Postgres
If you check the docs it states:
Technically, a primary key constraint is simply a combination of a unique constraint and a not-null constraint.
That's also true for multi-column primary keys (see here)
So, if ts is part of your primary key in the database (as the #Id indicates) it's simply not possible to insert null values in that column.
IMO Hibernate/Spring got nothing to do with that as
insert into ms.time_series (ts, name, reading) values (NULL, 'sensor1', 10.0)
should be equivalent to
insert into ms.time_series (name, reading) values ('sensor1', 10.0)

Insert attribute in table if it is not null using Hibernate

I have mapping class defined as:
#Table(name = "TEST_TABLE")
public class DBTestAccount
{
#Id
#Column(name = "UUID", nullable = false, length = 36)
private String uuid;
#Column(name = "REGION")
private String region;
#Column(name = "COUNTRY")
private String countryCode;
//getters and setters
}
Now I need to update the table. For that let's say I create following object:
DBTestAccount dbTestAccount = new DBTestAccount();
dbTestAccount.setUuid("testUUID");
dbTestAccount.setRegion("testRegion");
dbTestAccount.setCountryCode(null);
Now let's say initially in the table we have a record that has some value of COUNTRY. Inserting the above object will replace the value and make COUNTRY null. I want that it should update the data, but if the column is null, then it should ignore and do not update it. If it is non-null then it should update it. How to achieve this in hibernate? Is there an annotation to do so? If not then what is the possible solution (except using if - else). Can I create a custom annotation for this?
PS:
The underlying database is PostgreSQL.
The example you are describing can't be present in the database, because the object is not an entity yet, as it is created with new keyword and it isn't yet persisted in the database.
From your explanation, what I got, is that you want to save only changed attributes. For that purpose hibernate has the Dynamic Update annotation.

Is Hibernate 4.3 #DynamicUpdate really does not include null values?

I have been trying to implement entity updating using #DynamicUpdate. Documentation (http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/) says:
dynamicInsert / dynamicUpdate (defaults to false): specifies that INSERT / UPDATE SQL should be generated at runtime and contain only the columns whose values are not null.
But I didn't manage to make it works, so I dug into the sources of AbstractEntityPersister, and saw this:
generateUpdateString( propsToUpdate, j, oldFields, j == 0 && rowId != null )
It is a method for generating SQL query string, based on 'propsToUpdate' which is boolean array obtained from:
getPropertiesToUpdate( dirtyFields, hasDirtyCollection );
where 'dirtyFields' is an integer array of id's of 'dirty' columns.
But nowhere in
getPropertiesToUpdate(final int[] dirtyProperties, final boolean hasDirtyCollection)
i was able to find mechanism for checking if modified column is not null, so even when entity i want to merge has some null fields, all of them are updated in the DB, overriding existing data with nulls.
My question is: where is an error in my reasoning?
EDIT:
Here's my code, as Chaitanya requested:
Entity:
#SuppressWarnings("serial")
#Entity(name = "t_quiz_groups")
#DynamicUpdate
#SelectBeforeUpdate
public class QuizGroupEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_id")
private long id;
#Column(name = "description", nullable = false)
private String description;
#Column(name = "create_date", nullable = false)
#Column(name = "create_date")
private Calendar createDate;
+setters and getters
Then, I have a service (#Transactional) method:
public void update(long groupId, String newDescription) throws ServiceException {
QuizGroupEntity quizGroupEntity = quizRepository.getGroupById(groupId);
ExpectedNotNull.of(quizGroupEntity, RegistryErrorCodes.QUIZ_GROUP_NOT_EXISTS);
quizGroupEntity.setCreateDate(null); //for testing purposes i am setting another
field as null (shouldnt be updated then, right?)
quizRepository.lock(quizGroupEntity, LockModeType.WRITE);
quizGroupEntity.updateDescription(newDescription); // new description
quizRepository.merge(quizGroupEntity);
}
And now, in AbstractEntityPersiste, method:
getPropertiesToUpdate( dirtyFields, hasDirtyCollection );
is called, and dirtyFields[] consists of two 'dirty' columns: [0,2] - and that is correct, those two columns were modified (date and description, date set to null)
Then, generateUpdateString( propsToUpdate, j, oldFields, j == 0 && rowId != null ) is called, with 'propsToUpdate' looking like this:
[true, false, true, false, true]
Which is wrong, because indeed first and third columns were modified, but first one is set to null, that is why
generateUpdateString( propsToUpdate, j, oldFields, j == 0 && rowId != null )
Generates query:
[update t_quiz_groups set create_date=?, description=?, version=? where group_id=? and version=?]
That will modify create_date, and override it with null value.

Null pointer exception while using hibernate

I am using Hibernate and spring. this is my model class
#Entity
#NamedNativeQueries({#NamedNativeQuery(
name = "CSI_TARGET",
query = "select * from CSITARGET('CSIINDEX',2)",
resultClass = CSITarget.class)})
public class CSITarget {
#Column(name="csi_target")
private BigDecimal csi_target;
#Id
#Column(name="financialyearfrom" ,nullable = true)
private int financialyearfrom =0;
#Column( name="at_yearhalf" , nullable = true)
private String at_yearhalf = "";
public BigDecimal getCsi_target() {
return csi_target;
}
public void setCsi_target(BigDecimal csi_target) {
this.csi_target = csi_target;
}
public int getFinancialyearfrom() {
return financialyearfrom;
}
public void setFinancialyearfrom(int financialyearfrom) {
this.financialyearfrom = financialyearfrom;
}
public String getAt_yearhalf() {
return at_yearhalf;
}
public void setAt_yearhalf(String at_yearhalf) {
this.at_yearhalf = at_yearhalf;
}
I am using Hibernate to call a stored procedure in postgres database. The stored procedure returns a table which is mapped to this model class. Now my problem is, the table that is returned from the database contains a null value. I am in the need of doing some manipulations on the data. Now since the null value is mapped to the bean class I am getting a null pointer exception. How can I make hibernate ignore the null values in the database and set a default value for the corresponding property in the bean class. As you can see I have used nullable property also. It does'nt work.
financialyearfrom is int which cannot be assigned null value though corresponding column you might be having null value in database if column is defined as nullable.
For handling null values in java primitive variables, remove nullable=true and possible add default value 0, so all null value from db column would convert to 0 or 0.0 etc.
Or
Use wrapper class instead i.e. Integer which will allow you to retain null value assigned from db column.
Again, above two approaches are in general applicable for primitive variables using in Hibernate entities.
Further to add #ID column shouldn't be nullable IMO, if it corresponds to primary key column (in most of the cases it is) so your code would be wrong as primary key column doesn't allow null values.
Would it be possible to use COALESCE in your query to assign a default value to that field if its null? If that's possible that's probably the best way to fix this issue w/o having to tweak your code too much.

How to insert records using the Entity Manager without defining the Primary Key field?

I have trying to insert a record into the database (MySQL), using Entity Class and Entity Manager. But one of the field is an auto incrementing primary key, so unless I provide an value manually, the insertion is not successful.
public boolean newContributor(String name, String email, String country, Integer contactable, String address) {
Contributors contributor = new Contributors(); //entity class
contributor.setId(??????); //this is Primary Key field and is of int datatype
contributor.setName(name);
contributor.setEmail(email);
contributor.setCountry(country);
contributor.setContactable(contactable);
contributor.setAddress(address);
em.persist(contributor);
return true;
}
How to solve such problem? Is there a way to tell the entity manager to attempt the insert without the ID field and use NULL value instead.
Update: Here is a portion of the entity class defining the id
...
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 50)
....
Is there a way to tell the entity manager to attempt the insert without the ID field and use NULL value instead?
Sure. You need to remove the #NotNull annotation for id field in the #Entity definition, and also remove the row:
contributor.setId(??????);
from method newContributor(). The reason for this is that the #NotNull annotation enforces a validation check in the JPA stack. It doesn't mean that the field is NOT NULL at a database level. See here a discussion about this issue.
The rest of the code looks fine.

Categories

Resources