Call Stored Procedure in Grails (Step by step) - grails

Can anyone tell me how to call stored procedure from Grails which is present in User-defined path.

For that purpose you can use Groovy Sql.
To use Groovy SQL:
import groovy.sql.Sql
Request a reference to the datasource with def dataSource or def sessionFactory for transactions
Create an Sql object using def sql = new Sql(dataSource) or def sql = new Sql(sessionFactory.currentSession.connection())
Use Groovy SQL as required
Grails will manage the connection to the datasource automatically.
Note: dataSource and sessionFactory are beans that you would have to inject in your pojo/bean class.
So to execute sql code written on your file:
String sqlFilePath = grailsApplication.parentContext.servletContext.getRealPath("/data/proc.sql")
String sqlString = new File(sqlFilePath).text
Sql sql = new Sql(sessionFactory.currentSession.connection())
sql.execute(sqlString)
This will execute any sql statements written in your file on your sql server.

From JDriven's blog post Grails Goodness: Using Hibernate Native SQL Queries:
In the following sample we create a new Grails service and use a
Hibernate native SQL query to execute a selectable stored procedure
with the name organisation_breadcrumbs. This stored procedure takes
one argument startId and will return a list of results with an id,
name and level column.
class OrganisationService {
// Auto inject SessionFactory we can use
// to get the current Hibernate session.
def sessionFactory
List breadcrumbs(final Long startOrganisationId) {
// Get the current Hiberante session.
final session = sessionFactory.currentSession
// Query string with :startId as parameter placeholder.
final String query = 'select id, name, level from organisation_breadcrumbs(:startId) order by level desc'
// Create native SQL query.
final sqlQuery = session.createSQLQuery(query)
// Use Groovy with() method to invoke multiple methods
// on the sqlQuery object.
final results = sqlQuery.with {
// Set domain class as entity.
// Properties in domain class id, name, level will
// be automatically filled.
addEntity(Organisation)
// Set value for parameter startId.
setLong('startId', startOrganisationId)
// Get all results.
list()
}
results
}
}
In the sample code we use the addEntity() method to map the query
results to the domain class Organisation. To transform the results
from a query to other objects we can use the setResultTransformer()
method.
Hibernate (and therefore Grails if we use the Hibernate plugin)
already has a set of transformers we can use. For example, with the
org.hibernate.transform.AliasToEntityMapResultTransformer (in place of addEntity) each result row is transformed into a Map where the column aliases are the keys of the map.
resultTransformer = AliasToEntityMapResultTransformer.INSTANCE

Related

Execute stored procedure for viewmodel class returntype

i am trying to write some code in mvc to get the userdata by id. Here i am using Viewmodel class that contains all the parameters as Database table. and i am using enterprise library to execute the stored procedure. Here is the code in my Data Access Layer i tried..
public UserEntity GetUserByID(int userID)
{
DatabaseProviderFactory factory = new DatabaseProviderFactory();
Database db = factory.Create("MySqlConnection");
DbCommand dbc = db.GetStoredProcCommand("uspGetUserByID");
dbc.CommandType = CommandType.StoredProcedure;
db.AddInParameter(dbc, "userID", DbType.Int32, userID);
return db.ExecuteDataSet(dbc).Tables[0];
}
here UserEntity is my viewmodel class. here Executedataset doesn't work because the returntype is not dataset but viewmodel class. i want the code to execute the stored procedure..
thank you..
If you want to return your custom type without manually constructing it (either from a DataSet or an IDataReader) then you can use accessors.
In your case it would look like this:
public UserEntity GetUserByID(int userID)
{
DatabaseProviderFactory factory = new DatabaseProviderFactory();
Database db = factory.Create("MySqlConnection");
IEnumerable<UserEntity> results = db.ExecuteSprocAccessor<UserEntity>("uspGetUserByID", userID);
return results.FirstOrDefault();
}
This assumes that the UserEntity can be mapped from the stored procedure result set (e.g. column names are the same name as the property names). If not, then you would need to create a custom mapper. See Retrieving Data as Objects from the Developer's Guide for more information about accessors. Also if there is an issue passing in the userID parameter then you may have to create a parameter mapper as in Defining Parameter Mappers.

How to model stored procedure records in Grails?

I need to call some stored procedures that return their own kinds of records, that are not directly mapped to tables or views.
I have used stored procedures in the past with groovy.sql.Sql and plain (unmodelled) Maps, but for this application I would like to model those records with something akin to domain classes, in order to define data types, data binding, validation, associations to other entities, and so on.
What is the best way to do so?
Should I model the stored procedure records as proper domain classes (entities) and then try to disable (or redefine) their database persistence? How?
Should I use non-domain POJOs where I selectively enable the features I need? (such as validation with #Validatable) How can I handle associations then? (Associations arise when the record returned from the SP contains a foreign key to some other persisted entity.)
If you want data binding, validation and associations to be maintained in an easy way then you should go with the Domain approach.
To disable database persistence for a domain class you can add static mapWith = "none" to a domain class and a table won't be created for that domain class.
Sample Entity class:
#ToString
public class SPTest {
Long idField
User user
GroupIntegrationKey integrationKey
static constraints = {
}
static mapWith = "none"
}
Stored Procedure statement:
SELECT id AS idField, user_id AS user, key AS integrationKey FROM
my_domain;
In order to map the result of the SP to the entity you can use result transformers.
Query query = session.createSQLQuery("CALL getSPData()");
List<Map> results = query.with {
resultTransformer = AliasToEntityMapResultTransformer.INSTANCE
list()
}
Now iterate over list and create a new entity object
List<MyDomain> list = results.collect {
new MyDomain(it)
}
System.err.println(list)
Drawbacks:
You can not map identifier field
You would have to iterate over result again to create entity objects
You can not map hasMany relationships
If you want to go with pojo, then in that case you would have to create your own version of getters to get associated objects.

Grails pure sql and domain class

I have an existing MySQL database and in grails controller i want use pure SQL query instead of GORM (it's too difficult to run the reverse engineering plugin).
I want return json object
So my idea is, in the controller, to execute a sql query and map the result to an object and render that object in json (i have see the grails REST tutorial anyway).
To map the sql query result to an object, can i use the grails domain class or i must create a pure groovy object?
Can i use the command:
grails create-domain-class
or i must create a DTO groovy object (in src/groovy folder)?
You don't need to create a DTO to solve your problem you just need to use an HQL, like this:
def result = Domain.executeQuery("FROM DOMAIN WHERE conditions");
render result as JSON;
I hope this solve your problem.
If you want to pass the native sql then you can also use spring jdbcTemplate.
Configuration:
import org.springframework.jdbc.core.JdbcTemplate
beans = {
..........
jdbcTemplate(JdbcTemplate) {
dataSource = ref('dataSource')
}
}
Controller:
def jdbcTemplate
List actionMethod(){
String query = "your pure native query example select ........from table"
List results = jdbcTemplate.queryForList(queryStr)
return results as JSON
])
}
Create DTO object and map the required columns one by one .I used the DTO approach since my number of columns to be mapped were quite less.
If your result is simple enough, you can use groovy.sql.Sql class and do the querying directly in the controller:
def results = []
Sql db = new Sql( dataSource )
db.eachRow( "select avg( rating ) as rating, main_profile_id as id from profile" ) {
results << [ it.id, it.rating ]
}
db.close()

Grails domain object with select query

I have a requirement where in I need to get some 10 different colums from 5 different tables of oracle. Basically I want to execute a custom select query and I want to understand from you guys whether I can create a custom domain object and get data populated in this domain object using grails. Some thoughts some links where I can explore more, it would be great.
Thanks
You can use straight Groovy SQL with the dataSource bean. This is an example from an integration test.
def dataSource
#Test
public void sql() {
Sql sql = new Sql(dataSource)
List<GroovyRowResult> results = sql.rows("select * from user")
println results[0].first_name
println results[0].<COLUMN_NAME>
}
Whatever raw SQL you need to use can be put inside of the call to sql.rows() and the result is a List of GroovyRowResult which can essentially be treated like a Map
You can try something like suggested here:
Mapping result of a native SQL query to Grails domain class
import com.acme.domain.*
def sessionFactory
sessionFactory = ctx.sessionFactory // this only necessary if your are working with the Grails console/shell
def session = sessionFactory.currentSession
def query = session.createSQLQuery("select f.* from Foo where f.id = :filter)) order by f.name");
query.addEntity(com.acme.domain.Foo.class); // this defines the result type of the query
query.setInteger("filter", 88);
query.list()*.name;

Spring Data #Query on fields

The #Query on the property retrieves the values only if I retrieve the entity from the DB.
#NodeEntity
public class Team
{
#GraphId
private Long nodeId;
#RelatedTo (type = "PREVIOUSLY_KNOWN_AS")
private Team previouslyKnownAs;
#Query ("START t=node({self}) MATCH t-[:PREVIOUSLY_KNOWN_AS]-other RETURN other")
private Iterable<Team> aliases;
}
The below test works only if I uncomment the line to read it explicitly from the db. Why is it necessary? I see the query being run after the save(t) but the alias field is null if I doesn't read it from DB by uncommenting the line
#Test
public void alias()
{
Team t = new Team();
t.setName("Alpharetta One");
Team prev = new Team();
prev.setName("Previous Name");
teamRepo.save(prev);
t.setPreviouslyKnownAs(prev);
teamRepo.save(t);
//t = teamRepo.findOne(t.getNodeId());//only works if I uncomment
assertNotNull(t.getAliases());
}
Try
t=teamRepo.save(t);
I dont think that the save operation will update the POJO which you give to it, while the returned Object should be a managed enttiy.
The key lies in the reference documentation
The #Query annotation leverages the delegation infrastructure supported by Spring Data Neo4j.It provides dynamic fields which, when accessed, return the values selected by the provided query language expression.
Since it is a dynamic field, the value isnt instanciated but instead fetched from the DB every time the get method is called. To do this, a proxy object has to be used. However there is no way for SDN to change your t Object reference to the proxy object, and thats why its not working, if you are not using the entity returned by save().

Resources