Skip to content

Commit d5193e4

Browse files
schaudergregturn
authored andcommitted
DATAJDBC-154 - Include some basic getting started documentation in the readme.
1 parent 3c9765c commit d5193e4

File tree

1 file changed

+201
-3
lines changed

1 file changed

+201
-3
lines changed

README.adoc

Lines changed: 201 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,220 @@
11
= Spring Data JDBC
22

3-
The primary goal of the http://projects.spring.io/spring-data[Spring Data] project is to make it easier to build Spring-powered applications that use data access technologies. *Spring Data JDBC* offers the popular Repository abstraction based on JDBC
3+
The primary goal of the http://projects.spring.io/spring-data[Spring Data] project is to make it easier to build Spring-powered applications that use data access technologies. *Spring Data JDBC* offers the popular Repository abstraction based on JDBC.
44

55
== This is NOT an ORM
66

77
Spring Data JDBC does not try to be an ORM. It is not a competitor to JPA. Instead it is more of a construction kit for your personal ORM that you can define the way you like or need it.
88

99
This means that it does rather little out of the box. But it offers plenty of places where you can put your own logic, or integrate it with the technology of your choice for generating SQL statements.
1010

11+
== Maven Coordinates
12+
13+
```xml
14+
<dependency>
15+
<groupId>org.springframework.data</groupId>
16+
<artifactId>spring-data-jdbc</artifactId>
17+
<version>1.0.0.BUILD-SNAPSHOT</version>
18+
</dependency>
19+
```
20+
1121
== Features
1222

1323
=== CRUD operations
1424

25+
In order use Spring Data JDBC you need the following:
26+
27+
1. An entity with an attribute marked as _id_ using the spring datas https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/annotation/Id.html[`@Id`] annotation.
28+
29+
public class Person {
30+
@Id
31+
Integer id;
32+
}
33+
34+
2. A repository
35+
36+
public interface PersonRepository extends CrudRepository<Person, Integer> {}
37+
38+
3. Add `@EnableJdbcRepositories` to your application context configuration.
39+
40+
4. Make sure your application context contains a bean of type `DataSource`.
41+
42+
Now you can get an instance of the repository interface injected into your beans and use it:
43+
44+
```java
45+
@Autowired
46+
private PersonRepository repository;
47+
48+
public void someMethod() {
49+
Person person = repository.save(new Person());
50+
}
51+
```
52+
53+
=== Id generation
54+
55+
Spring Data JDBC uses the id to identify entities but also to determine if an entity is new or already existing in the database.
56+
If the id is `null` or of a primitive type and `0` or `0.0` the entity is considered new.
57+
58+
When your data base has some autoincrement column for the id column the generated value will get set in the entity after inserting it into the database.
59+
60+
There are few ways to tweak this behavior.
61+
If you don't like the logic to distinguish between new and existing entities you can implement https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Persistable.html[`Persistable`] with your entity and overwrite `isNew()` with your own logic.
62+
63+
One important constraint is that after saving an entity the entity shouldn't be _new_ anymore.
64+
With autoincrement columns this happens automatically since the the id gets set by Spring Data with the value from the id column.
65+
If you are not using autoincrement columns you can use that using a `BeforeSave`-listener which sets the id of the entity (see below).
66+
67+
=== NamingStrategy
68+
69+
When you use the standard implementations of `CrudRepository` as provided by Spring Data JDBC it will expect a certain table structure.
70+
You can tweak that by providing a https://github.com/spring-projects/spring-data-jdbc/blob/master/src/main/java/org/springframework/data/jdbc/mapping/model/NamingStrategy.java[`NamingStrategy`] in your application context.
71+
1572
=== Events
1673

74+
Spring Data Jdbc triggers events which will get publish to any matching `ApplicationListener` in the application context.
75+
For example the following listener will get invoked before an aggregate gets saved.
76+
77+
``` java
78+
@Bean
79+
public ApplicationListener<BeforeSave> timeStampingSaveTime() {
80+
81+
return event -> {
82+
83+
Object entity = event.getEntity();
84+
if (entity instanceof Category) {
85+
Category category = (Category) entity;
86+
category.timeStamp();
87+
}
88+
};
89+
}
90+
```
91+
92+
.Available events
93+
|===
94+
| Type | Published ...
95+
96+
| https://github.com/spring-projects/spring-data-jdbc/blob/master/src/main/java/org/springframework/data/jdbc/mapping/event/AfterDelete.java[`AfterDelete`]
97+
| after an aggregate root got deleted.
98+
99+
| https://github.com/spring-projects/spring-data-jdbc/blob/master/src/main/java/org/springframework/data/jdbc/mapping/event/BeforeDelete.java[`BeforeDelete`],
100+
| before an aggregate root gets deleted.
101+
102+
| https://github.com/spring-projects/spring-data-jdbc/blob/master/src/main/java/org/springframework/data/jdbc/mapping/event/AfterSave.java[`AfterSave`],
103+
| after an aggregate root gets saved, i.e. inserted or updated.
104+
105+
| https://github.com/spring-projects/spring-data-jdbc/blob/master/src/main/java/org/springframework/data/jdbc/mapping/event/AfterDelete.java[`BeforeSave`],
106+
| before an aggregate root gets saved, i.e. inserted or updated but after the decision was made if it will get updated or deleted.
107+
The event has a reference to an https://github.com/spring-projects/spring-data-jdbc/blob/master/src/main/java/org/springframework/data/jdbc/core/conversion/AggregateChange.java[`AggregateChange`] instance.
108+
The instance can be modified by adding or removing https://github.com/spring-projects/spring-data-jdbc/blob/master/src/main/java/org/springframework/data/jdbc/core/conversion/DbAction.java[`DbAction`]s.
109+
110+
| https://github.com/spring-projects/spring-data-jdbc/blob/master/src/main/java/org/springframework/data/jdbc/mapping/event/AfterDelete.java[`AfterCreation`]
111+
| after an aggregate root got created from a database `ResultSet` and all it's property set
112+
|===
113+
114+
115+
=== MyBatis
116+
117+
For each operation in `CrudRepository` Spring Data Jdbc will execute multiple statements.
118+
If there is a https://github.com/mybatis/mybatis-3/blob/master/src/main/java/org/apache/ibatis/session/SqlSessionFactory.java[`SqlSessionFactory`] in the application context, it will checked if it offers a statement for each step.
119+
If one is found that statement will be used (including its configured mapping to an entity).
120+
121+
The name of the statement is constructed by concatenating the fully qualified name of the entity type with `Mapper.` and a string determining the kind of statement.
122+
E.g. if an instance of `org.example.User` is to be inserted Spring Data Jdbc will look for a statement named `org.example.UserMapper.insert`.
123+
124+
Upon execution of the statement an instance of [`MyBatisContext`] will get passed as an argument which makes various arguments available to the statement.
125+
126+
[cols="default,default,default,asciidoc"]
127+
|===
128+
| Name | Purpose | CrudRepository methods which might trigger this statement | Attributes available in the `MyBatisContext`
129+
130+
| `insert` | Insert for a single entity. This also applies for entities referenced by the aggregate root. | `save`, `saveAll`. |
131+
`getInstance`:
132+
the instance to be saved
133+
134+
`getDomainType`: the type of the entity to be saved.
135+
136+
`get(<key>)`: id of the referencing entity, where `<key>` is the name of the back reference column as provided by the `NamingStrategy`.
137+
138+
139+
| `update` | Update for a single entity. This also applies for entities referenced by the aggregate root. | `save`, `saveAll`.|
140+
`getInstance`: the instance to be saved
141+
142+
`getDomainType`: the type of the entity to be saved.
143+
144+
| `delete` | Delete a single entity. | `delete`, `deleteById`.|
145+
`getId`: the id of the instance to be deleted
146+
147+
`getDomainType`: the type of the entity to be deleted.
148+
149+
| `deleteAll.<propertyPath>` | Delete all entities referenced by any aggregate root of the type used as prefix via the given property path.
150+
Note that the type used for prefixing the statement name is the name of the aggregate root not the one of the entity to be deleted. | `deleteAll`.|
151+
152+
`getDomainType`: the type of the entities to be deleted.
153+
154+
| `deleteAll` | Delete all aggregate roots of the type used as the prefix | `deleteAll`.|
155+
156+
`getDomainType`: the type of the entities to be deleted.
157+
158+
| `delete.<propertyPath>` | Delete all entities referenced by an aggregate root via the given propertyPath | `deleteById`.|
159+
160+
`getId`: the id of the aggregate root for which referenced entities are to be deleted.
161+
162+
`getDomainType`: the type of the entities to be deleted.
163+
164+
165+
| `findById` | Select an aggregate root by id | `findById`.|
166+
167+
`getId`: the id of the entity to load.
168+
169+
`getDomainType`: the type of the entity to load.
170+
171+
| `findAll` | Select all aggregate roots | `findAll`.|
172+
173+
`getDomainType`: the type of the entity to load.
174+
175+
| `findAllById` | Select a set of aggregate roots by ids | `findAllById`.|
176+
177+
`getId`: list of ids of the entities to load.
178+
179+
`getDomainType`: the type of the entity to load.
180+
181+
182+
| `findAllByProperty.<propertyName>` | Select a set of entities that is referenced by another entity. The type of the referencing entity is used for the prefix. The referenced entities type as the suffix. | All `find*` methods.|
183+
184+
`getId`: the id of the entity referencing the entities to be loaded.
185+
186+
`getDomainType`: the type of the entity to load.
187+
188+
| `count` | Count the number of aggregate root of the type used as prefix | `count` |
189+
190+
`getDomainType` the type of aggregate roots to count.
191+
|===
192+
193+
== Features planned for the not to far future
194+
195+
=== Query annotation
196+
197+
Just annotate a method with a SQL query to use this whenever the method gets called.
198+
199+
=== MyBatis per method support
200+
201+
The current MyBatis supported is rather elaborate in that it allows to execute multiple statements for a single method call.
202+
But sometimes less is more and it should be possible to annotate a method with a simple annotation to identify a SQL statement in a MyBatis mapping to be executed.
203+
204+
== Spring Boot integration
205+
206+
There is https://github.com/schauder/spring-data-jdbc-boot-starter[preliminary Spring Boot integration].
207+
208+
Currently you will need to build it locally.
209+
17210
== Getting Help
18211

19-
== Quick Start
212+
Right now the best source of information is the source code in this repository.
213+
Especially the integration tests (type `t` and then `IntegrationTests.java`)
214+
215+
We are keeping an eye on the (soon to be created) https://stackoverflow.com/questions/tagged/spring-data-jdbc[spring-data-jdbc tag on stackoverflow].
216+
217+
If you think you found a bug, or have a feature request please https://jira.spring.io/browse/DATAJDBC/?selectedTab=com.atlassian.jira.jira-projects-plugin:summary-panel[create a ticket in our issue tracker].
20218

21219
== Execute Tests
22220

@@ -33,7 +231,7 @@ This will execute unit tests and integration tests using an in-memory database.
33231

34232
=== Running tests with a real database
35233

36-
To run the integration tests against a specific database you nned to have the database running on your local machine and then execute.
234+
To run the integration tests against a specific database you need to have the database running on your local machine and then execute.
37235

38236
[source]
39237
----

0 commit comments

Comments
 (0)