Spring MyBatis pass default value if null or empty - mybatis

Is there a way to pass a default value (zero) to MyBatis #Insert(<script>… … testVal … values … #{TESTVAL} … …) query using #Results({ #Result(property=“testVal”, column=“TESTVAL”, value=“${testVal:0}”, jdbcType.INTEGER), … …}) ? Or something similar?

Related

Default return value for JPA query

I have a JPA query
#Query(value = "SELECT SUM(total_price) FROM ... WHERE ...", nativeQuery = true)
which works as expected when there are matching records. But when there are no matching records, the query returns null.
How can I return zero(0) instead of null when no records are found?
You can change return type to be an Optional;
#Query(value = "SELECT SUM(total_price) FROM ... WHERE ...", nativeQuery = true)
Optional<Integer> getSum(...);
Or you can wrap this getSum() with a default method;
#Query(..)
Integer getSum(...);
default Integer safeGetSum(..) {
return Optional.ofNullable(getSum(..)).orElse(0);
}
More info on null handling in repositories
When the return value is not a list, or some wrapper (plus some others check below), & there are no matching records, the return will be null, so there is no slick way to handle this with some defaultValue=0 through #Query
The absence of a query result is then indicated by returning null. Repository methods returning collections, collection alternatives, wrappers, and streams are guaranteed never to return null but rather the corresponding empty representation.
A native SQL option is COALESCE which returns the first non-null expression in the arg list
SELECT COALESCE(SUM(total_price),0) FROM ...

mybatis - Passing multiple parameters on #One annotation

I am trying to access a table in my Secondary DB whose name I am obtaining from my Primary DB. My difficulty is to pass the "DB-Name" as a parameter into my secondary query, (BTW I am using MyBatis annotation based Mappers).
This is my Mapper
#SelectProvider(type = DealerQueryBuilder.class, method = "retrieveDealerListQuery")
#Results({
#Result(property="dealerID", column="frm_dealer_master_id"),
#Result(property="dealerTypeID", column="frm_dealer_type_id", one=#One(select="retrieveDealerTypeDAO")),
#Result(property="dealerName", column="frm_dealer_name")
})
public List<Dealer> retrieveDealerListDAO(#Param("firmDBName") String firmDBName);
#Select("SELECT * from ${firmDBName}.frm_dealer_type where frm_dealer_type_id=#{frm_dealer_type_id}")
#Results({
#Result(property="dealerTypeID", column="frm_dealer_type_id"),
#Result(property="dealerType", column="frm_dealer_type")
})
public DealerType retrieveDealerTypeDAO(#Param("firmDBName") String firmDBName, #Param("frm_dealer_type_id") int frm_dealer_type_id);
The firmDBName I have is obtained from my "Primary DB".
If I omit ${firmDBName} in my second query, the query is trying to access my Primary Database and throws out table "PrimaryDB.frm_dealer_type" not found. So it is basically trying to search for a table named "frm_dealer_type" in my Primary DB.
If I try to re-write the #Result like
#Result(property="dealerTypeID", column="firmDBName=firmDBName, frm_dealer_type_id=frm_dealer_type_id", one=#One(select="retrieveDealerTypeDAO")),
It throws an error that Column"firmDBName" does not exist.
Changing ${firmDBName} to #{firmDBName} also did not help.
I did refer to this blog - here
I want a solution to pass my parameter firmDBName from my primary query into secondary query.
The limitation here is that your column must be returned by the first #SELECT.
If you look at the test case here you will see that parent_xxx values returned by the first Select.
Your DealerQueryBuilder must select firmDBName as a return value and your column must map the name of the return column to that.
Your column definition is always wrong, it should be:
{frm_dealer_type_id=frm_dealer_type_id,firmDBName=firmDBName} or whatever it was returned as from your first select.
Again you can refer to the test case I have above as well as the documentation here http://www.mybatis.org/mybatis-3/sqlmap-xml.html#Nested_Select_for_Association

Pass nothing (not null) to the server if the argument is None

I have a model:
case class MyModel(
id: Pk[Long] = NotAssigned,
startsAt: Option[DateTime] = None,
addedAt: Option[DateTime] = None
)
object MyModel {
// .....................
SQL("""
INSERT INTO my_table(starts_at)
VALUES ({startsAt})
"""
).on('startsAt -> newItem.startsAt).executeInsert()
}
Both startst_at and added_at have a default value of now() in Postgresql and don't allow null values in them. It doesn't cause any error for addedAt (because I never pass it to the server from the client) but it does cause the error for startsAt if it's not specified at newItem.startsAt and, thus, is equal to None and, thus, it's being passed as null.
org.postgresql.util.PSQLException: ERROR: null value in column "starts_at" violates not-null constraint
What I want is be able to specify startsAt whenever I want it and pass it to the server, meaning if I specify it then that value should be passed to the server, if not - nothing should be passed and the server should use its default value now(). I don't want to specify the default value at the client because it's already set at the server at the db level.
How about this SQL fix:
insert into my_table(starts_at)
values (COALESCE({startsAt}, now())
Updated: requirement is to use the default value of the column
The only way that I know of to get the server to use the default value of a column in an insert, is not to mention that column in the columns list. For example (not tested):
startsAt.map { date =>
SQL("""insert into my_table(starts_at) values({startsAt})""")
.on('startsAt -> date)
.execute()
}.orElse {
SQL("""insert into my_table() values()""")
.execute()
}

how to insert null or valid value in nullable column of database in EF 4.1

I am in scenerio where I need to inset a dateTime value in the database using the EF 4.1.
DateColumn in database in Nullable.
While creating the entity i am filling it as,
DTCLOSE = referenceProblemLog.DateClosed.HasValue ?
referenceProblemLog.DateClosed.Value.ToFeedFormatString() :
System.DBNull.Value.ToString(),
where ToFeedFormatString is an extension method.
Now problem i observed is, if I have a proper value then it is inserted correctly but
when i dont have a proper date value, i want to insert NULL in database column. However EF is saving column with Empty string
I tried to change the StoreGeneratedPattern for the field to "Identity" but problem with it is, I cant assign value to DTCLose field.
How can i have both the things?
1. EF should insert NULL in database when proper value is not there
2. proper value otherwise
Please help
Thanks
Anup
This is wrong System.DBNull.Value.ToString() because at the end you will have string object, ToString() never returns null.
You have to set DTCLOSE = null
Also, with EF you don't have to use DBNull, you just define nullable property and set it null
You Can use this :
Nullable<DateTime> date=null;
var entity = new Model()
{
GoDate = date
};
DataContext.Models.Add(entity);
DataContext.SaveChanges();

EntLib Way to Bind "Null" Value to Parameter

I wish to pass Null Value to the parameter as follow:
_db.AddInParameter(dbCommand, "Id", DBNull.Value, myContactPerson.Id);
I am receiving the following error :
"can not convert "System.DBNull to System.Data.DbType".
I know the meaning of this error.
But i need to supply null value to myContactPerson.Id
How can i achieve this ?
If myContactPerson.Id isn't an auto-number, then why not just pass 0.
DBType should be passed in that parameter and should match your the dbtype (string, int, etc.) for the table that you are comparing with in your database. You would replace your value field "myContactPerson.Id" with DBNull.Value to always pass the null value.