How can we disable deepvalidate on global level in grails 4? as in our case on saving one domain object its trying to save all internal domain objects leading to different errors like unique constraint and all.
If GORM entity references some other entities, then during its constraints evaluation (validation) the constraints of the referenced entity could be evaluated also, if needed. There is a special parameter cascadeValidate in the entity mappings section, which manage the way of this cascaded validation happens. You can do this in three ways |
1. Define cascadeValidate as mapping per domain where needed: class Author { Publisher publisher static mapping = { publisher(cascadeValidate: "none") } } class Publisher { String name static constraints = { name blank: false } } |
The following table presents all options, which can be used: none: Will not do any cascade validation at all for the association. default: The DEFAULT option. GORM performs cascade validation in some cases. dirty: Only cascade validation if the referenced object is dirty via the DirtyCheckable trait. If the object doesn’t implement DirtyCheckable, this will fall back to default. owned: Only cascade validation if the entity owns the referenced object. |
2. It is possible to set the global option for the cascadeValidate: Globally disable cascadeValidate in Grails 3 or 4 using: grails { gorm { failOnError = true 'default' { mapping = { cache true version false autoTimestamp false id generator:'assigned' '*'(cascadeValidate: 'none') // this one is the option to disable deep validate } } } } |
3. Alternatevely you can disable when call save() or merge() using: new Account().save(validate: true, deepValidate: false) |
Grails gorm reference link: Reference https://gorm.grails.org/latest/hibernate/manual/#_cascade_constraints_validation |
Showing posts with label grails hibernate. Show all posts
Showing posts with label grails hibernate. Show all posts
Wednesday, September 29, 2021
GRAILS 4 - how to disable deepvalidate in grails globally | Add ability to control cascading validation independently
Sunday, October 18, 2020
Grails on Groovy - Clear and Flush Current Hibernate Session Data and Evict All Query Cache Data | Clearing Hibernate Query Cache in Grails
Hibernate already has support for query cache. And we know that when we perform a big task there are huge number queries remain in our cache factory. And more important that in most cases we don't need this caches so as a result cache factory getting full with unusual cache data.
This could be a performance issue - so it's better we clear cache on our own responsibility after a big task completed. |
Below are the procedure to flush and clear current session (hibernate session) data so that cache factory have enough space for further execution. |
import org.hibernate.SessionFactory import grails.util.Holders private static SessionFactory _sessionFactory static Boolean flushAndClearCache() { try { sessionFactory.currentSession.flush() sessionFactory.currentSession.clear() sessionFactory.getCache().evictEntityRegions() sessionFactory.getCache().evictCollectionRegions() sessionFactory.getCache().evictDefaultQueryRegion() sessionFactory.getCache().evictQueryRegions() return true } catch (Throwable ex) { log.error(ex.ex) return false } } static <T> T getBean(Class<T> requiredType) { try { return Holders.applicationContext.getBean(requiredType) } catch (Throwable e) { return null } } static SessionFactory getSessionFactory() { _sessionFactory = _sessionFactory ?: (_sessionFactory = getBean(SessionFactory)) } |
Thursday, July 27, 2017
Grails Groovy SessionFactory EnityKey SessionStatistics | Grails Get SQL Table Name From Domain Class | Grails Get SQL Table Field Name From Domain Class
Grails Groovy SessionFactory EnityKey SessionStatistics | Grails Get SQL Table Name From Domain Class | Grails Get SQL Table Field Name From Domain Class.
c
import org.hibernate.SessionFactory
import grails.util.Holders
import org.hibernate.engine.spi.EntityKey import org.hibernate.stat.SessionStatistics /** * Created by pritom on 27/07/2017. */ class HibernateSessionUtil { private static SessionFactory _sessionFactory public static void main(String[] args) { def domainInstance = "DomainClass".proxy(100L) checkIfObjectExistsInSession(domainInstance) } static void evictAllEntities() { SessionStatistics sessionStatistics = sessionFactory.currentSession.getStatistics() sessionStatistics.getEntityKeys().asList().each { EntityKey entityKey -> evict(entityKey.persisterClass.proxy(entityKey.identifier.toString().toLong())) } } static void evict(def instance) { sessionFactory.currentSession.evict(instance) } static Boolean checkIfObjectExistsInSession(def domainInstance) { SessionStatistics sessionStatistics = sessionFactory.currentSession.getStatistics() println("Total ${sessionStatistics.getEntityKeys().asList().size()} Object Exists in Session") Boolean exists = false sessionStatistics.getEntityKeys().asList().find { EntityKey entityKey -> println("EntityName=${entityKey.entityName},EntityId=${entityKey.identifier.toString()}") if (domainInstance.class.canonicalName.equals(entityKey.entityName) && domainInstance.id.toString().equals(entityKey.identifier.toString())) { exists = true } } return exists } static String getTableFieldName(Class clazz, String fieldName) { return sessionFactory.getClassMetadata(clazz).propertyMapping.getColumnNames(fieldName)[0] } static String getTableName(Class clazz) { return sessionFactory.getClassMetadata(clazz).getTableName() } static boolean flushAndClearCache() { try { sessionFactory.currentSession.flush() sessionFactory.currentSession.clear() sessionFactory.getCache().evictEntityRegions() sessionFactory.getCache().evictCollectionRegions() sessionFactory.getCache().evictDefaultQueryRegion() sessionFactory.getCache().evictQueryRegions() return true } catch (Exception ex) { ex.printStackTrace() return false } } static SessionFactory getSessionFactory() { _sessionFactory = _sessionFactory ?: (_sessionFactory = Holders.applicationContext.getBean(SessionFactory)) } static { EntityKey.metaClass.getPersisterClass = { return persister.entityTuplizer.mappedClass } } }
c
Grails Groovy Hibernate | Hibernate Criteria Builder | Projection | Custom Projection | Group By Projection | PropertyProjection
Grails Groovy Hibernate | Hibernate Criteria Builder | Projection | Custom Projection | Group By Projection | PropertyProjection.
It's easy to add projection custom. We can add custom projection and custom group by property.
But you want to make it simpler then you can use below function easily:
It's easy to add projection custom. We can add custom projection and custom group by property.
import org.hibernate.criterion.Projections import org.hibernate.criterion.Projection import org.hibernate.criterion.PropertyProjection import org.hibernate.Criteria import org.hibernate.criterion.CriteriaQuery import org.hibernate.HibernateException org.hibernate.criterion.ProjectionList projectionList = [] ProjectionList projectionList = [] projectionList.add(new PropertyProjection("id") { @Override public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException { return "this_.id as y0_" } }) projectionList.add(new PropertyProjection("created") { @Override public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException { return "MAX(this_.created) as y1_" } }) projectionList.add(Projections.groupProperty("belongsTo.id")) PropertyProjection groupBy = new PropertyProjection("id", true) { @Override public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException { return "belongsto1_.id as y1_" } @Override public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { return "belongsto1_.id" } } projectionList.add(groupBy) Closure closure = { setProjection(projectionList) } List list = Domain.createCriteria().list { and closure }
But you want to make it simpler then you can use below function easily:
import org.hibernate.criterion.CriteriaSpecification import org.hibernate.criterion.Projections import org.hibernate.type.DoubleType import org.hibernate.type.Type resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP) projections { groupProperty("id", "id") groupProperty("name", "name") addProjectionToList(Projections.sqlProjection( "sum(id * 0.2) as totalPrice", ["totalPrice"] as String[], [DoubleType.INSTANCE] as Type[], ), "complexSqlCalculation") }
Grails | Groovy | Create Criteria | Hibernate Criteria Builder | Custom Criteria Order | Custom Sort By | Custom Order Criteria
Grails | Groovy | Create Criteria | Hibernate Criteria Builder | Custom Criteria Order | Custom Sort By | Custom Order Criteria.
In Grails we may need sometime to add sort / order by with some aggregate function as sum of two fields. Suppose we have a Grails / Groovy domain which has two field named "amount" and "tax", now we want to sort by sum of these two fields. So we can do that using below sample code:
In Grails we may need sometime to add sort / order by with some aggregate function as sum of two fields. Suppose we have a Grails / Groovy domain which has two field named "amount" and "tax", now we want to sort by sum of these two fields. So we can do that using below sample code:
import groovy.lang.Closure import org.hibernate.Criteria import org.hibernate.HibernateException import org.hibernate.criterion.CriteriaQuery import org.hibernate.criterion.Order as CriterionOrder Closure closure = { addOrder(new CriterionOrder("amount", params.dir) { @Override String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { return "(this_.amount + this_.tax) asc" } }) projections { property("id") property("amount") } } List list = Domain.createCriteria().list { and closure }
Thursday, July 20, 2017
Grails | Groovy | Hibernate | Query Builder | HibernateCriteriaBuilder | Criteria Builder | Criteria Builder To SQL | Grails Create Criteria To SQL Conversion | Grails Convert Query Builder To MySQL | Criteria Builder SQL Restriction | SQLRestriction | Grails SQL Restriction
Grails | Groovy | Hibernate | Query Builder | HibernateCriteriaBuilder | Criteria Builder | Criteria Builder To SQL | Grails Create Criteria To SQL Conversion | Grails Convert Query Builder To MySQL | Criteria Builder SQL Restriction | SQLRestriction | Grails SQL Restriction.
Below a query | criteria builder. We will convert below hibernate criteria builder to SQL our-self. So with this feature we can check each and every query generated by hibernate query builder and can take necessary step if we need any. With this feature we also can retrieve query binding parameters. At first we will see our grails domain structure I used in my example codes. Below example also to show how we can use SQL restriction in criteria builder. In SQL Restriction section we can write plain SQL.
Below a query | criteria builder. We will convert below hibernate criteria builder to SQL our-self. So with this feature we can check each and every query generated by hibernate query builder and can take necessary step if we need any. With this feature we also can retrieve query binding parameters. At first we will see our grails domain structure I used in my example codes. Below example also to show how we can use SQL restriction in criteria builder. In SQL Restriction section we can write plain SQL.
class Subscription { Long id Account account } class Account { Long id User createdBy } class User { Long id String name }
Now below is our criteria builder (as well as we called it closure will pass to criteria builder to execute it):
def test() { Closure closure = { HibernateCriteriaBuilder builder = delegate setMaxResults(2) String a1 = CriteriaToSql.createAlias(builder, "account") String a2 = CriteriaToSql.createAlias(builder, "createdBy", "${a1}.createdBy")
println(builder.properties.sql_aliases) gt("id", -1L) ne("code", "NOT_EQ_CODE") gt("${a1}.id", -2L) gt("${a2}.id", -3L) sqlRestriction("exists (select a.id from account AS a where a.id=this_.id)") projections { property("code") } order("updated", "desc") order("id", "desc") } CriteriaToSql.check(Subscription.class, closure) render("") }
And finally our desired class which will product SQL from given criteria builder:
import grails.orm.HibernateCriteriaBuilder import org.apache.commons.lang.StringEscapeUtils import org.hibernate.Criteria import org.hibernate.engine.spi.LoadQueryInfluencers import org.hibernate.engine.spi.SessionFactoryImplementor import org.hibernate.internal.CriteriaImpl import org.hibernate.internal.SessionImpl import org.hibernate.loader.OuterJoinLoader import org.hibernate.loader.OuterJoinableAssociation import org.hibernate.loader.PropertyPath import org.hibernate.loader.criteria.CriteriaJoinWalker import org.hibernate.loader.criteria.CriteriaLoader import org.hibernate.loader.criteria.CriteriaQueryTranslator import org.hibernate.persister.entity.OuterJoinLoadable import org.hibernate.sql.JoinType import java.lang.reflect.Field /** * Created by pritom on 17/07/2017. */ class CriteriaToSql { static int counter = 0 static void check(Class domainClass, Closure closure) { Criteria criteria = domainClass.createCriteria().buildCriteria { and closure } CriteriaImpl c = (CriteriaImpl) criteria SessionImpl s = (SessionImpl) c.getSession() SessionFactoryImplementor factory = (SessionFactoryImplementor) s.getSessionFactory() String[] implementors = factory.getImplementors(c.getEntityOrClassName()) LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers() CriteriaLoader loader = new CriteriaLoader((OuterJoinLoadable) factory.getEntityPersister(implementors[0]), factory, c, implementors[0], loadQueryInfluencers) CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, c, domainClass.canonicalName, "this_") CriteriaJoinWalker walker = new CriteriaJoinWalker( (OuterJoinLoadable) factory.getEntityPersister(implementors[0]), translator, factory, criteria, domainClass.canonicalName, loadQueryInfluencers ) Field f = OuterJoinLoader.class.getDeclaredField("sql") f.setAccessible(true) String sql = (String) f.get(loader), printable = "" int index = 0, max = 250 while (true) { if (sql.length() > (index * max) + max) { printable = printable + "\r\n" + sql.substring(index * max, max + (index * max)) index++ } else { printable = printable + "\r\n" + sql.substring(index * max) break } } println("SQL_QUERY=${printable}") f = CriteriaLoader.class.getDeclaredField("querySpaces") f.setAccessible(true) println("SQL_ALIASES=${walker.getAssociations()*.rhsAlias}") println("PARAMETERS=${translator.getQueryParameters().positionalParameterValues}") } static Map getSql(Class domainClass, Closure closure) { Criteria criteria = domainClass.createCriteria().buildCriteria { and closure } CriteriaImpl c = (CriteriaImpl) criteria SessionImpl s = (SessionImpl) c.getSession() SessionFactoryImplementor factory = (SessionFactoryImplementor) s.getSessionFactory() String[] implementors = factory.getImplementors(c.getEntityOrClassName()) LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers() CriteriaLoader loader = new CriteriaLoader((OuterJoinLoadable) factory.getEntityPersister(implementors[0]), factory, c, implementors[0], loadQueryInfluencers) CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, c, domainClass.canonicalName, "this_") CriteriaJoinWalker walker = new CriteriaJoinWalker( (OuterJoinLoadable) factory.getEntityPersister(implementors[0]), translator, factory, criteria, domainClass.canonicalName, loadQueryInfluencers ) Field f = OuterJoinLoader.class.getDeclaredField("sql") f.setAccessible(true) String sql = (String) f.get(loader) Map parts = [ select: sql.substring(7, sql.indexOf("from")), from: sql.substring(sql.indexOf("from") + 5, sql.indexOf("where")), where: sql.substring(sql.indexOf("where") + 6), joins: [:] ] walker.getAssociations().each { OuterJoinableAssociation assoc -> String key = assoc.propertyPath.property PropertyPath propertyPath = assoc.propertyPath while (true) { if (propertyPath.parent?.property) { key = propertyPath.parent.property + "." + key propertyPath = propertyPath.parent } else { break } } parts.joins[key] = [domain: assoc.propertyPath.property, alias: assoc.rhsAlias] } int lastIndex = -1 translator.getQueryParameters().positionalParameterValues.each { param1 -> int index = parts.where.indexOf("?", lastIndex) if (index >= 0) { param1 = param1.rawValue() param1 = param1 instanceof String ? "'${StringEscapeUtils.escapeSql(param1)}'" : param1 parts.where = parts.where.substring(0, index) + param1 + parts.where.substring(index + 1) lastIndex = index + param1.toString().length() } } return parts } static String createAlias(HibernateCriteriaBuilder criteriaBuilder, String field, String aliasPath = field, JoinType joinType = JoinType.INNER_JOIN) { if (!criteriaBuilder.properties.lixt) { criteriaBuilder.metaClass.lixt = [:] } Criteria subCriteria = criteriaBuilder.criteria.subcriteriaList.find { it.path == aliasPath } if(subCriteria) { return subCriteria.alias } else { String alias = "${field}xxxxxxxx${++counter}" criteriaBuilder.createAlias(aliasPath, alias, joinType) /* The below variable is SQL alias path */ String sqlAlias = alias.substring(0, 10) + (criteriaBuilder.properties.lixt.size() + 1) + "_" criteriaBuilder.properties.lixt[alias] = sqlAlias return alias } } }
And finally we would have below output:
[PV4736-12429, MS2431-12503] [PV4736-12429, MS2431-12503] SQL_QUERY= select this_.code as y0_ from subscription this_ inner join account accountxxx1_ on this_.account_id=accountxxx1_.id inner join user createdbyx2_ on accountxxx1_.created_by_id=createdbyx2_.id where (this_.id>? and this_.code<>? and accountxxx1_.id>? and createdbyx2_.id>? and exists (select a.id from account AS a where a.id=this_.id)) order by this_.updated desc, this_.id desc SQL_ALIASES=[accountxxx1_, createdbyx2_] PARAMETERS=[-1, NOT_EQ_CODE, -2, -3]
Wednesday, March 15, 2017
How can I determine whether an entity already exists in the Hibernate session cache
Hibernate use first & second level cache to store database data fetch from database and actually its Hibernate Session. So when your read data from database it stores in Hibernate Session. There is a separate Hibernate Session for each request. Sometimes we need to identify if any object exists in session or not. Below is a simple code snippet to determine if any object exists in current Hibernate Session or not. The most important thing is that you must use proxy to reference the object to check.
package com.pkm
import grails.util.Holders
import org.hibernate.SessionFactory
import org.hibernate.engine.spi.EntityKey
import org.hibernate.stat.SessionStatistics
/**
* Created by pritom on 15/03/2017.
* Session.html#getStatistics
* SessionStatistics.html#getEntityKeys
*/
class HibernateSessionUtil {
private static SessionFactory sessionFactory
public static void main(String[] args) {
def domainInstance = "DomainClass".proxy(100L)
checkIfObjectExistsInSession(domainInstance)
}
static Boolean checkIfObjectExistsInSession(def domainInstance) {
SessionStatistics sessionStatistics = sessionFactory.currentSession.getStatistics()
println("Total ${sessionStatistics.getEntityKeys().asList().size()} Object Exists in Session")
Boolean exists = false
sessionStatistics.getEntityKeys().asList().find { EntityKey entityKey ->
println("EntityName=${entityKey.entityName},EntityId=${entityKey.identifier.toString()}")
if (domainInstance.class.canonicalName.equals(entityKey.entityName) &&
domainInstance.id.toString().equals(entityKey.identifier.toString())) {
exists = true
}
}
return exists
}
static {
sessionFactory = sessionFactory ?: (sessionFactory = getBean(SessionFactory))
}
static <T> T getBean(Class<T> requiredType) {
try {
return Holders.applicationContext.getBean(requiredType)
}
catch (Exception e) {
return null
}
}
}
Monday, November 7, 2016
Tuesday, December 31, 2013
Hibernate/grails left join or inner join when using create criteria
Hibernate/grails left join or inner join or join when using create criteria. If you do not use
'CriteriaSpecification.LEFT_JOIN', then it would be a inner join.
Here is the example as suppose 'User' belongsTo 'Role' which is nullable.
Now you want to left join 'Role' when creating criteria on 'User', then do
the following. It would take all 'User' row where 'Role' is null or not.
But if you do not use 'CriteriaSpecification.LEFT_JOIN', then it would take only
'User.role' is not null.
import org.hibernate.criterion.CriteriaSpecification; List userList = User.createCriteria().list { eq("isActive", true); createAlias("role", "__role", CriteriaSpecification.LEFT_JOIN) eq("__role.someProperty", "some value"); }
Subscribe to:
Posts (Atom)