Spring Data procedure invocation - stored-procedures

I have a procedure, which returns rows.
Each row has one column, which is a string, like so..
create procedure myproc(IN var1 varchar(255), IN var2 varchar(255))
begin
select col3 from table1 where col1 = var1 and col2 = val2;
end;
/
I want to invoke this procedure using Spring Data.
The Spring Data manual says, I could invoke this procedure
from a method in a Repository, which is annotated with #Procedure
like so..
#Procedure(procedureName = "myproc")
List<String> myproc(String val1, String val2);
My question is.. how should the repository class, which will contain the annotated method,
be declared as
Should it be like this..
class MyRepository extends JpaRepository<T,ID>{
}
If yes, what type parameter should I use for T and ID
Should I necessarily create an entity class, to replace T above
If yes, what is a suitable type for ID in this case
And would I have to create a table in the database to hold this entity?

Spring data jpa follows the 'domain driven design'.
So I think it is mandatory to pass Domain.
Your domain is like
#Entity
public class Person {
#Id
#GeneratedValue
private Long id;
.... getter setter...
}
Your repository should be like below
public interface PersonRepository extends JpaRepository<Person, Long> {
#Procedure(procedureName = "myproc")
List<String> myproc(String val1, String val2);
}
You need to pass your domain class as T
You need to pass data type of id field of Person class as a ID, In this case it's a Long
For more info by example https://dzone.com/articles/calling-stored-procedures-from-spring-data-jpa

Related

SpringData Cassandra Java Adapter - Using UDTs in Map Columns

I am using the 1.5.1 version of the Cassandra adapter for Java, and I am attempting to insert a record to a table having a Map column that uses a UDT as the column value (key is just a varchar). I created the table using cqlsh and am able to insert to it in CQL just fine. When i try to use a CassandraTemplate...insert(), though, all I get is:
UserTypeResolver must not be null
My UDT class is defined as:
#UserDefinedType("iss_type")
public class IssueType {
#CassandraType(type = DataType.Name.VARCHAR)
private String issue_code;
#CassandraType(type = DataType.Name.VARCHAR)
private String issue_name;
#CassandraType(type = DataType.Name.TIMESTAMP)
private Date issue_start;
#CassandraType(type = DataType.Name.TIMESTAMP)
private Date issue_end;
And my table is defined as
#Table
public class IssueMap {
#PrimaryKeyColumn(
type = PrimaryKeyType.PARTITIONED)
private UUID map_id;
#Column
private Map<String, IssueType> issue_map;
In my config, i have:
#Bean
public CassandraMappingContext cassandraMapping()
throws ClassNotFoundException {
BasicCassandraMappingContext mappingContext = new BasicCassandraMappingContext();
mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(cluster().getObject(),"campaign_management"));
return mappingContext;
}
Is there something I am missing here? Or is it just not possible to define columns this way? I realize I could just use a query builder to create the CQL and do the insert, but I was hoping to be able to make full use of the Cassandra template features.

How to get a node using index

I have an entity Place:
#NodeEntity
#TypeAlias(value="Place")
public class Place implements Serializable{
private static final long serialVersionUID = 1L;
#GraphId
private Long nodeId;
#JsonProperty("id")
#Indexed(unique=true)
private String id;
//...
}
And I try to get a node based on its id attribute this way:
String pfc = "1234";
(Node)template.getIndex(Place.class, "id").get("id", pfc).getSingle()
But I'm having this exception :
java.lang.IllegalStateException: Index name for class java.lang.String id rel: false idx: true must differ from the default name: Place
Must I necessairly add a name to the index?
If yes, how should I do for the existent data?
Which version are you using? In SDN 3.x for Neo4j 2.x the indexes and constraints are used automatically.
I would use a PlaceRepository with a findById() method.
Or in general cypher queries that access place like this:
MATCH (p:Place {id:{id}})-->(x)
RETURN x
You can access them manually with template.merge() or template.findByLabelAndProperty() which I would only recommend when you know what you're doing.

Grails: legacy database: foreign key that has not the same type in each mapped table

So I have a grails model looking like this:
class Tree {
Long id;
String name;
static hasMany = [branches: Branch
}
class Branch {
Long id;
String name;
static belongsTo = [tree: Tree]
}
The issue is that in DB, the Tree id is a number, while the tree_id in the Branch table is a varchar.
The db model is a de facto foreign key that is not enforced at all as a constraint.
Gorm generate a query that is not handled by my database: it tries to bing a numerical value where text is expected:
ERROR util.JDBCExceptionReporter - ORA-01722: invalid number
How can I tell GORM to convert the value before binding the parameter ?
I looked in the join table config but I did not find anything relevant.
Have you tried using sqlType in column definition in mappings?
class Branch {
Long id
String name
static belongsTo = [tree: Tree]
static mapping = {
tree column: 'TREE_ID', sqlType: "char"
}
}
Unable to test right now, but do let me know.

EntityFramework: Stored Procedure that returns a custom Poco instead of complex type

I have a Custom POCO (Already existing und used in my project).
public class MyPoco()
{
public string MyPocoName {get; set;}
public string MyPocoParentName {get; set;}
}
I have also a stored procedures that returns a list of (MyPocoName,MyPocoParentName) values.
I couldn't set MyPoco as the return type of this procedure in the Function import wizard.
I don't want to create a new custom type that have the same proporties as MyPoco.
Is there any way that could specify the return type of the stored procedure to be MyPoco.
Thanks.
Yes there is a way but you must not use function import (adding stored procedures to your model doesn't make sense in this case). Use:
var data = objectContext.ExecuteStoreQuery<MyPoco>("spName", SqlParams);
to call you stored procedure.
I had to add the param list after the spName:
var results =
this.Context.Database.SqlQuery<MyPoco>(
"spName #param1, #param2, #param3",
new SqlParameter("#param1", var1),
new SqlParameter("#param2", var2),
new SqlParameter("#param3", var3));

Executing Method Against DataContext Returning Inserted ID

Is there any way to use DataContext to execute some explicit SQL and return the auto-increment primary key value of the inserted row without using ExecuteMethodCall? All I want to do is insert some data into a table and get back the newly created primary key but without using LINQ (I use explicit SQL in my queries, just using LINQ to model the data).
Cheers
EDIT: Basically, I want to do this:
public int CreateSomething(Something somethingToCreate)
{
string query = "MyFunkyQuery";
this.ExecuteCommand(query);
// return back the ID of the inserted value here!
}
SOLUTION
This one took a while. You have to pass a reference for the OUTPUT parameter in your sproc in your parameter list of the calling function like so:
[Parameter(Name = "InsertedContractID", DbType = "Int")] ref System.Nullable<int> insertedContractID
Then you have to do
insertedContractID = ((System.Nullable<int>)(result.GetParameterValue(16)));
once you've called it. Then you can use this outside of it:
public int? CreateContract(Contract contractToCreate)
{
System.Nullable<int> insertedContractID = null; ref insertedContractID);
return insertedContractID;
}
Take heavy note of GetParameterValue(16). It's indexed to whichever parameter it is in your parameter list (this isn't the full code, by the way).
You can use something like this:
int newID = myDataContext.ExecuteQuery<int>(
"INSERT INTO MyTable (Col1, Col2) VALUES ({0}, {1});
SELECT Convert(Int, ##IDENTITY)",
val1, val2).First();
The key is in converting ##IDENTITY in type int, like Ben sugested.
If you insist on using raw sql queries, then why not just use sprocs for your inserts? You could get the identity returned through an output parameters.
I'm not the greatest at SQL, but I broke out LinqPad and came up with this. It's a big hack in my opinion, but it works ... kinda.
DataContext.ExecuteQuery<T>() returns an IEnumerable<T> where T is a mapped linq entity. The extra select I added will only populate the YourPrimaryKey property.
public int CreateSomething(Something somethingToCreate)
{
// sub out your versions of YourLinqEntity & YourPrimaryKey
string query = "MyFunkyQuery" + "select Convert(Int, SCOPE_IDENTITY()) as [YourPrimaryKey]";
var result = this.ExecuteQuery<YourLinqEntity>(query);
return result.First().YourPrimaryKey;
}
You'll need to modify your insert statement to include a SELECT ##Identity (SQL Server) or similar at the end.

Resources