{"id":13707960,"url":"https://github.com/mhewedy/spwrap","last_synced_at":"2025-05-05T14:42:09.823Z","repository":{"id":57721451,"uuid":"81202245","full_name":"mhewedy/spwrap","owner":"mhewedy","description":"Simple Stored Procedure call wrapper with no framework dependencies. ","archived":false,"fork":false,"pushed_at":"2019-04-20T14:38:46.000Z","size":4247,"stargazers_count":24,"open_issues_count":7,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-30T21:51:11.246Z","etag":null,"topics":["dao-interface","database","jdbc","spwrap","sql","stored-procedures"],"latest_commit_sha":null,"homepage":"https://github.com/mhewedy/spwrap-spring-boot-starter","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mhewedy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-07T11:46:05.000Z","updated_at":"2022-04-13T13:21:07.000Z","dependencies_parsed_at":"2022-09-26T21:41:28.868Z","dependency_job_id":null,"html_url":"https://github.com/mhewedy/spwrap","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhewedy%2Fspwrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhewedy%2Fspwrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhewedy%2Fspwrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhewedy%2Fspwrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mhewedy","download_url":"https://codeload.github.com/mhewedy/spwrap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252516160,"owners_count":21760738,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dao-interface","database","jdbc","spwrap","sql","stored-procedures"],"created_at":"2024-08-02T22:01:50.825Z","updated_at":"2025-05-05T14:42:09.806Z","avatar_url":"https://github.com/mhewedy.png","language":"Java","readme":"# spwrap\nStored Procedure caller; simply execute stored procedure from java code.    \n*Compatible with `jdk` \u003e= `1.5`, with only single dependency (`slf4j-api`)*\n\n[![Build Status](https://travis-ci.org/mhewedy/spwrap.svg?branch=master)](https://travis-ci.org/mhewedy/spwrap)\n[![Coverage Status](https://codecov.io/github/mhewedy/spwrap/coverage.svg?branch=master)](https://codecov.io/github/mhewedy/spwrap?branch=master)\n\n## Step 0: Create Stored Procedures:\n\nSuppose you have 3 Stored Procedures to save customer to database, get customer by id and list all customer.\n\nFor example here's SP code using HSQL:\n```sql\nCREATE PROCEDURE create_customer(firstname VARCHAR(50), lastname VARCHAR(50), OUT custId INT, \n        OUT code SMALLINT, OUT msg VARCHAR(50))\n    MODIFIES SQL DATA DYNAMIC RESULT SETS 1\n    BEGIN ATOMIC\n        INSERT INTO CUSTOMERS VALUES (DEFAULT, firstname, lastname);\n        SET custId = IDENTITY();\n        SET code = 0 -- success;\n    END\n\nCREATE PROCEDURE get_customer(IN custId INT, OUT firstname VARCHAR(50), OUT lastname VARCHAR(50), \n        OUT code SMALLINT, OUT msg VARCHAR(50)) \n    READS SQL DATA\n    BEGIN ATOMIC\n        SELECT first_name, last_name INTO firstname, lastname FROM customers WHERE id = custId;\n        SET code = 0 -- success;\n    END\n\nCREATE PROCEDURE list_customers(OUT code SMALLINT, OUT msg VARCHAR(50))\n    READS SQL DATA DYNAMIC RESULT SETS 1\n    BEGIN ATOMIC\n        DECLARE result CURSOR FOR SELECT id, first_name firstname, last_name lastname FROM CUSTOMERS;\n        OPEN result;\n        SET code = 0 -- success;\n    END\n```\n\u003e**NOTE**: Every Stored Procedure by default need to have 2 additional Output Parameters at the end of its parameter list. One of type `SMALLINT` and the other of type `VARCHAR` for result code and message respectively, where result code `0` means success. You can override the `0` value or remove this default behviour at all, [see the configuration wiki page](https://github.com/mhewedy/spwrap/wiki/Configurations).\n\n## Step 1: Create The DAO interface:\n```java\npublic interface CustomerDAO {\n\n    @StoredProc(\"create_customer\")\n    void createCustomer(@Param(VARCHAR) String firstName, @Param(VARCHAR) String lastName);\n\n    @StoredProc(\"get_customer\")\n    Customer getCustomer(@Param(INTEGER) Integer id);\t\n\t\n    @StoredProc(\"list_customers\")\n    List\u003cCustomer\u003e listCustomers();\n}\n```\n\n## Step 2: Map Output parameters and Result set (if any):\n\nBefore start using the `CustomerDAO` interface, one last step is required, to *map* the result of the `get_customer` and `list_customers` stored procedures.\n\n* `get_customer` stored procs returns the result as Output Parameters, so you need to have a class to implement `TypedOutputParamMapper` interface.\n* `list_customers` stored proc returns the result as Result Set, so you need to have a class to implement `ResultSetMapper` interface.\n\nLet's create Customer class to implement both interfaces (for `getCustomer` and `listCustomers`):\n\n```java\npublic class Customer implements TypedOutputParamMapper\u003cCustomer\u003e, ResultSetMapper\u003cCustomer\u003e {\n\n\tprivate Integer id;\n\tprivate String firstName, lastName;\n\n\tpublic Customer() {\n\t}\n\n\tpublic Customer(Integer id, String firstName, String lastName) {\n\t\tsuper();\n\t\tthis.id = id;\n\t\tthis.firstName = firstName;\n\t\tthis.lastName = lastName;\n\t}\n\n\tpublic Integer id() {\n\t\treturn id;\n\t}\n\n\tpublic String firstName() {\n\t\treturn firstName;\n\t}\n\n\tpublic String lastName() {\n\t\treturn lastName;\n\t}\n\t\n\t //You can acess result set columns/output parameters by name as well\n\t@Override\n\tpublic Customer map(Result\u003c?\u003e result) {\n\t\tif (result.isResultSet()) {\n\t\t\treturn new Customer(result.getInt(1), result.getString(2), result.getString(3));\n\t\t} else {\n\t\t\treturn new Customer(null, result.getString(1), result.getString(2));\n\t\t}\n\t}\n\n\t// for TypedOutputParamMapper\n\t@Override\n\tpublic List\u003cInteger\u003e getTypes() {\n\t\treturn Arrays.asList(VARCHAR, VARCHAR);\n\t}\n}\n```\nSee more examples on [spwrap-examples](https://github.com/mhewedy/spwrap-examples) github project and read more about [Mappers](https://github.com/mhewedy/spwrap/wiki/Mappers) in the wiki.\n\n\u003e**NOTE**: If your stored procedure returns a single **output parameter** with no result set, then you can use the `@Scalar` annotation and you will not need to provide a Mapper class yourself, the mapping will done for you. [see wiki page about scalars for more](https://github.com/mhewedy/spwrap/wiki/Scalar)\n\n\u003e**NOTE**: You can use [`@AutoMapper`s](https://github.com/mhewedy/spwrap/wiki/AutoMappers) to do the mapping for you instead of Mapping the Result object into your domain object yourself.\n\n## Step 3: Using the DAO interface:\n\nNow you can start using the interface to call the stored procedures:\n```java\nDataSource dataSource = ...\nDAO dao = new DAO.Builder(dataSource).build();\nCustomerDAO customerDao = dao.create(CustomerDAO.class);\n\ncustomerDao.createCustomer(\"Abdullah\", \"Muhammad\");\nCustomer customer = customerDao.getCustomer1(1);\nAssert.assertEquals(\"Abdullah\", customer.firstName());\n```\n## Installation\nGradle:\n```gradle\ncompile group: 'com.github.mhewedy', name: 'spwrap', version: '0.0.20'\n```\nMaven:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.mhewedy\u003c/groupId\u003e\n    \u003cartifactId\u003espwrap\u003c/artifactId\u003e\n    \u003cversion\u003e0.0.20\u003c/version\u003e\n\u003c/dependency\u003e\n```\n## Additional staff:\n\n* If you don't supply the stored procedure name to `@StoredProc`, it will use the method name by default.\n\n* `@Param` annotation should used for *ALL* method parameters and accepts the SQL Type per `java.sql.Types`.\n\n* If you don't want to tie your Domain Object with `spwrap` as of step 3 above, you can have another class to implement the Mapper interfaces (`TypedOutputParamMapper` and `ResultSetMapper`) and pass it to the annotaion `@Mapper` like:\n```java\n@Mapper(CustomResultSetMapper.class)\n@StoredProc(\"list_customers\")\nList\u003cCustomer\u003e listCustomers();\n```\n* `@Mapper` annotation overrides the mapping specified by the return type object, i.e. `spwrap` extract Mapping infromation from the return type class, and then override it with the classes set by `@Mapper` annotation if found.\n\n* Your Stored procedure can return output parameter as well as *One* Result set in one call, to achieve this use `Tuple` return type:\n```java\n@Mapper({MyResultSetMapper.class, MyOutputParameterMapper.class})\n@StoredProc(\"list_customers_with_date\")\nTuple\u003cCustomer, Date\u003e listCustomersWithDate();\n```\n## Limitations:\n* spwrap doesn't support INOUT parameters.\n\n* spwrap doesn't support returning multi-result sets from the stored procedure.\n\n* When the Stored procedure have input and output parameters, input parameters should come first and then the output parameters.\n\n## Database Support:\nBecause `spwrap` is based on JDBC API, theoretically it should support any Database Management System with a JDBC Driver, *However* it is [tested](https://travis-ci.org/mhewedy/spwrap) on **HSQL**, **MySQL**, **SQL Server** and **Oracle** with jdk **1.6**~~, **1.7** and **1.8**~~ (1.7 and 1.8 are remove to reduce build time). (Plan to test againest: `Postgresql`, `Sybase`, `DB2`)\n\nSee [wiki page](https://github.com/mhewedy/spwrap/wiki) for more info and test cases/[spwrap-examples](https://github.com/mhewedy/spwrap-examples) for more usage scenarios.\n","funding_links":[],"categories":["Java"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhewedy%2Fspwrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmhewedy%2Fspwrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhewedy%2Fspwrap/lists"}