├── .gitignore
├── LICENSE
├── README.md
├── WorkInProgress.md
└── jdbc-to-spring-jdbc-to-jpa.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HibernateJPAStepByStep
2 |
3 | ##Entities
4 |
5 | Student
6 | - id
7 | - passport_id
8 | - name
9 | - email
10 |
11 | Passport
12 | - id
13 | - number
14 | - issued_country
15 |
16 | Project
17 | - id
18 | - name
19 |
20 | StudentProject
21 | - id
22 | - student_id
23 | - project_id (Not really needed!!!)
24 | - task_id
25 |
26 | Task
27 | - id
28 | - project_id
29 | - desc
30 | - start_date
31 |
32 | Assumptions
33 | - Student can be in multiple Projects. A Project can have multiple Students. Many to Many.
34 | - Student can have one Passport and vice versa. One to One.
35 | - One Project can have Many Tasks. But one Task is associated with One Project Only. Many to One.
36 |
37 | ##Overview
38 | - Working with both Object-Oriented software and Relational Databases can be cumbersome and time consuming. Development costs are significantly higher due to a paradigm mismatch between how data is represented in objects versus relational databases.
39 | - http://www.agiledata.org/essays/dataModeling101.html and http://en.wikipedia.org/wiki/Data_modeling are good starting points for understanding these data modeling principles.
40 | - Hibernate takes care of the mapping from Java classes to database tables, and from Java data types to SQL data types.
41 | - Also data query and retrieval facilities
42 | - Hibernate’s design goal is to relieve the developer from 95% of common data persistence-related programming tasks
43 | - Hibernate is not a silver bullet. Not meant for application relying heavily on Stored Procedures.
44 |
45 | http://docs.jboss.org/hibernate/orm/5.0/userGuide/en-US/html_single/images/overview.png
46 |
47 | ##History
48 | - JPA 2.0 was released with the specifications of JAVA EE6 => JSR 317.
49 | - JPA 2.1 was released with the specification of JAVA EE7 => JSR 338.
50 | - SessionFactory (org.hibernate.SessionFactory) : A thread-safe (and immutable) representation of the mapping of the application domain model to a database. Acts as a factory for org.hibernate.Session instances. A SessionFactory is very expensive to create; there should be only one SessionFactory for an application for a given database. Maintains services that Hibernate uses across all Sessions such as second level caches, connection pools, transaction system integrations, etc.
51 | - Session (org.hibernate.Session) : A single-threaded, short-lived object conceptually modeling a "Unit of Work"[PoEAA]. Wraps a JDBC java.sql.Connection. Acts as a factory for org.hibernate.Transaction instances. Maintains a generally "repeatable read" persistence context (first level cache) of the application's domain model.
52 |
53 | ##Key Components
54 |
55 | - Entity : A JPA entity class is a POJO , i.e. an ordinary Java class that is annotated as having the ability to represent objects in the database
56 | - EntityManager : Manages the persistence operations on Entities.
57 | - EntityTransaction : One-to-one relationship with EntityManager. For each EntityManager, operations are maintained by EntityTransaction class.
58 | - EntityManagerFactory : Factory class of EntityManager.
59 | - Transaction (org.hibernate.Transaction) TODO - A single-threaded, short-lived object used by the application to demarcate individual physical transaction boundaries. It acts as an abstraction API to isolate the application from the underling transaction system in use (JDBC, JTA, CORBA, etc).
60 | - Domain Model : The POJO should have a no-argument constructor. Both Hibernate and JPA require this.
61 |
62 | ##Important Annotations
63 |
64 | - @Entity : Indicates the class as an entity or a table.
65 | - @Table : Indicates table name.
66 |
67 | - @Id : Identifies the column as a primary key of the Entity.
68 | - @GeneratedValue : Indicates that the column will be auto generated.
69 | - @Transient : Column will not be persisted.
70 | - @Column : Used to specify properties on a Entity Column
71 |
72 | - @JoinColumn : Used to specify the column used in the Join.
73 |
74 | - @ManyToMany Indicates a many-to-many relationship between the join Tables.
75 | - @ManyToOne Indicates a many-to-one relationship between the join Tables.
76 | - @OneToMany Indicates a one-to-many relationship between the join Tables.
77 | - @OneToOne Indicates a one-to-one relationship between the join Tables.
78 |
79 | - @NamedQueries Indicates list of named queries.
80 | - @NamedQuery Indicates a Query using static name.
81 |
82 | # Retrieving Data
83 | The Java Persistence API provides the following methods for querying entities.
84 | - The Java Persistence query language (JPQL) is a simple, string-based language similar to SQL used to query entities and their relationships.
85 | - The Criteria API is used to create typesafe queries using Java programming language APIs to query for entities and their relationships.
86 |
87 | Both JPQL and the Criteria API have advantages and disadvantages:
88 | - Just a few lines long, JPQL queries are typically more concise and more readable than Criteria queries. Developers familiar with SQL will find it easy to learn the syntax of JPQL.
89 | - JPQL named queries can be defined in the entity class using a Java programming language annotation or in the application’s deployment descriptor. Criteria queries are typesafe and therefore don’t require casting, as JPQL queries do.
90 | - JPQL queries are not typesafe, however, and require a cast when retrieving the query result from the entity manager. This means that type-casting errors may not be caught at compile time. JPQL queries don’t support open-ended parameters.
91 | - Criteria queries allow you to define the query in the business tier of the application. Although this is also possible using JPQL dynamic queries, Criteria queries provide better performance because JPQL dynamic queries must be parsed each time they are called.
92 | - The Criteria API is just another Java programming language API and doesn’t require developers to learn the syntax of another query language. Criteria queries are typically more verbose than JPQL queries and require the developer to create several objects and perform operations on those objects before submitting the query to the entity manager.
93 |
94 | ###Find
95 | ###Delete
96 | ##Java Persistence Query language
97 | - JPQL syntax is similar to the syntax of SQL.
98 | - JPQL works with Java Entity Classes
99 |
100 | ```
101 |
102 | SELECT ... FROM ...
103 | [WHERE ...]
104 | [GROUP BY ... [HAVING ...]]
105 | [ORDER BY ...]
106 |
107 | DELETE FROM ... [WHERE ...]
108 |
109 | UPDATE ... SET ... [WHERE ...]
110 |
111 | MAX
112 | Between A and B
113 |
114 | LIKE 'R%'
115 | ORDER BY columnname ASC
116 |
117 | @NamedQuery(query = "", name = "")\
118 | entitymanager.createNamedQuery
119 | entitymanager.createQuery("Complete Query");
120 |
121 | Queries with Parameters
122 |
123 | @NamedQueries({
124 | @NamedQuery(name="name1",
125 | query="Query1"),
126 | @NamedQuery(name="name2",
127 | query="Query2"),
128 | })
129 |
130 |
131 | ```
132 | ##Criteria Query
133 | TODO
134 |
135 | ##Eager and Lazy Fetching
136 |
137 | # Bidirectional relationships
138 | - The inverse side of a bidirectional relationship must refer to its owning side by using the mappedBy element of the @OneToOne, @OneToMany, or @ManyToMany annotation. The mappedBy element designates the property or field in the entity that is the owner of the relationship.
139 | - The many side of many-to-one bidirectional relationships must not define the mappedBy element. The many side is always the owning side of the relationship.
140 | - For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.
141 | - For many-to-many bidirectional relationships, either side may be the owning side.
142 |
143 | ## Cascading
144 | - Entities that use relationships often have dependencies on the existence of the other entity in the relationship. For example, a line item is part of an order; if the order is deleted, the line item also should be deleted. This is called a cascade delete relationship.
145 | - The javax.persistence.CascadeType enumerated type defines the cascade operations that are applied in the cascade element of the relationship annotations. Table 32-1 lists the cascade operations for entities.
146 |
147 | ##Embeddable Classes
148 | - Embeddable classes have the same rules as entity classes but are annotated with the javax.persistence.Embeddable annotation instead of @Entity.
149 |
150 | The following embeddable class, ZipCode, has the fields zip and plusFour:
151 |
152 | @Embeddable
153 | public class ZipCode {
154 | String zip;
155 | String plusFour;
156 | ...
157 | }
158 |
159 | This embeddable class is used by the Address entity:
160 |
161 | @Entity
162 | public class Address {
163 | @Id
164 | protected long id
165 | String street1;
166 | String street2;
167 | String city;
168 | String province;
169 | @Embedded
170 | ZipCode zipCode;
171 | String country;
172 | ...
173 | }
174 |
175 | ## Mapping Strategies : Inheritance Relationships to Database Entitities
176 | You can configure how the Java Persistence provider maps inherited entities to the underlying datastore by decorating the root class of the hierarchy with the annotation javax.persistence.Inheritance. The following mapping strategies are used to map the entity data to the underlying database:
177 | - A single table per class hierarchy
178 | - A table per concrete entity class
179 | - A “join” strategy, whereby fields or properties that are specific to a subclass are mapped to a different table than the fields or properties that are common to the parent class
180 |
181 |
182 |
183 | ##About in28Minutes
184 | - At in28Minutes, we ask ourselves one question everyday. How do we create more effective trainings?
185 | - We use Problem-Solution based Step-By-Step Hands-on Approach With Practical, Real World Application Examples.
186 | - Our success on Udemy and Youtube (2 Million Views & 12K Subscribers) speaks volumes about the success of our approach.
187 | - While our primary expertise is on Development, Design & Architecture Java & Related Frameworks (Spring, Struts, Hibernate) we are expanding into the front-end world (Bootstrap, JQuery, Angular JS).
188 |
189 | ###Our Beliefs
190 | - Best Course are interactive and fun.
191 | - Foundations for building high quality applications are best laid down while learning.
192 |
193 | ###Our Approach
194 | - Problem Solution based Step by Step Hands-on Learning
195 | - Practical, Real World Application Examples.
196 | - We use 80-20 Rule. We discuss 20% things used 80% of time in depth. We touch upon other things briefly equipping you with enough knowledge to find out more on your own.
197 | - We will be developing a demo application in the course, which could be reused in your projects, saving hours of your effort.
198 | - All the code is available on Github, for most steps.
199 |
200 | ###Useful Links
201 | - [Our Website](http://www.in28minutes.com)
202 | - [Youtube Courses](https://www.youtube.com/user/rithustutorials/playlists)
203 | - [Udemy Courses](https://www.udemy.com/user/in28minutes/)
204 | - [Facebook](http://facebook.com/in28minutes)
205 | - [Twitter](http://twitter.com/in28minutes)
206 | - [Google Plus](https://plus.google.com/u/3/110861829188024231119)
207 |
208 | ###Other Courses
209 | - [Spring Framework](https://www.udemy.com/spring-tutorial-for-beginners/)
210 | - [Maven](http://www.in28minutes.com/p/maven-tutorial-for-beginners.html)
211 | - [Eclipse](http://www.in28minutes.com/p/eclipse-java-video-tutorial.html)
212 | - Java
213 | * [Java](https://www.youtube.com/watch?v=Y4ftqcYVh5I&list=PLE0D4634AE2DFA591&index=1)
214 | * [Java Collections](http://www.in28minutes.com/p/java-collections-framework-video.html)
215 | * [Java OOPS Concepts](https://www.udemy.com/learn-object-oriented-programming-in-java/)
216 | - [Design Patterns](http://www.in28minutes.com/p/design-patterns-tutorial.html)
217 | - [JUnit](https://www.udemy.com/junit-tutorial-for-beginners-with-java-examples/)
218 | - [C](https://www.udemy.com/c-tutorial-for-beginners-with-puzzles/)
219 | - [C Puzzles](https://www.udemy.com/c-puzzles-for-beginners/)
220 | - [Javascript](https://www.youtube.com/watch?v=6TZdD-FR6CY)
221 | - [More Courses on Udemy](https://www.udemy.com/user/in28minutes/)
222 | * Java Servlets and JSP : Your first web application in 25 Steps
223 | * Learn Spring MVC in 25 Steps
224 | * Learn Struts in 25 Steps
225 | * Learn Hibernate in 25 Steps
226 | * 10 Steps to Professional Java Developer
227 | - [Java Interview Guide](http://www.in28minutes.com/p/buy-our-java-interview-guide.html)
228 | * Core Java
229 | * Advanced Java
230 | * Spring, Spring MVC
231 | * Struts
232 | * Hibernate
233 | * Design Patterns
234 | * 400+ Questions
235 | * 23 Videos
236 |
--------------------------------------------------------------------------------
/WorkInProgress.md:
--------------------------------------------------------------------------------
1 | pom.xml
2 | ```
3 |
5 | 4.0.0
6 | com.in28minutes
7 | jpa-hibernate-step-by-step
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.2.3.RELEASE
11 | 5.0.6.Final
12 |
13 |
14 |
15 |
16 | org.hibernate
17 | hibernate-entitymanager
18 | ${hibernate.version}
19 |
20 |
21 |
22 | org.springframework
23 | spring-context
24 | ${spring-framework.version}
25 |
26 |
27 |
28 | org.springframework
29 | spring-tx
30 | ${spring-framework.version}
31 |
32 |
33 |
34 | org.springframework
35 | spring-orm
36 | ${spring-framework.version}
37 |
38 |
39 |
40 | org.jboss.spec.javax.transaction
41 | jboss-transaction-api_1.2_spec
42 | 1.0.0.Final
43 |
44 |
45 |
46 |
47 | c3p0
48 | c3p0
49 | 0.9.1.2
50 |
51 |
52 |
53 | org.hsqldb
54 | hsqldb
55 | 2.3.2
56 |
57 |
58 |
59 | log4j
60 | log4j
61 | 1.2.14
62 | runtime
63 |
64 |
65 |
66 |
67 | junit
68 | junit
69 | 4.12
70 | test
71 |
72 |
73 |
74 | org.springframework
75 | spring-test
76 | ${spring-framework.version}
77 | test
78 |
79 |
80 |
81 |
82 | ```
83 | Readme.md
84 | ```
85 | - Working with both Object-Oriented software and Relational Databases can be cumbersome and time consuming. Development costs are significantly higher due to a paradigm mismatch between how data is represented in objects versus relational databases.
86 | - http://www.agiledata.org/essays/dataModeling101.html and http://en.wikipedia.org/wiki/Data_modeling are good starting points for understanding these data modeling principles.
87 | - Hibernate takes care of the mapping from Java classes to database tables, and from Java data types to SQL data types.
88 | - Also data query and retrieval facilities
89 | - Hibernate’s design goal is to relieve the developer from 95% of common data persistence-related programming tasks
90 | - Hibernate is not a silver bullet. Not meant for application relying heavily on Stored Procedures.
91 |
92 | http://docs.jboss.org/hibernate/orm/5.0/userGuide/en-US/html_single/images/overview.png
93 |
94 | SessionFactory (org.hibernate.SessionFactory)
95 | A thread-safe (and immutable) representation of the mapping of the application domain model to a database. Acts as a factory for org.hibernate.Session instances.
96 |
97 | A SessionFactory is very expensive to create; there should be only one SessionFactory for an application for a given database. Maintains services that Hibernate uses across all Sessions such as second level caches, connection pools, transaction system integrations, etc.
98 |
99 | Session (org.hibernate.Session)
100 | A single-threaded, short-lived object conceptually modeling a "Unit of Work"[PoEAA].
101 |
102 | Wraps a JDBC java.sql.Connection. Acts as a factory for org.hibernate.Transaction instances. Maintains a generally "repeatable read" persistence context (first level cache) of the application's domain model.
103 |
104 | Transaction (org.hibernate.Transaction)
105 | A single-threaded, short-lived object used by the application to demarcate individual physical transaction boundaries. It acts as an abstraction API to isolate the application from the underling transaction system in use (JDBC, JTA, CORBA, etc).
106 |
107 | Domain Model
108 | The POJO should have a no-argument constructor. Both Hibernate and JPA require this.
109 |
110 |
111 | Hibernate Bean Validation
112 |
113 | Bidirectional relationships must follow these rules.
114 | - The inverse side of a bidirectional relationship must refer to its owning side by using the mappedBy element of the @OneToOne, @OneToMany, or @ManyToMany annotation. The mappedBy element designates the property or field in the entity that is the owner of the relationship.
115 | - The many side of many-to-one bidirectional relationships must not define the mappedBy element. The many side is always the owning side of the relationship.
116 | - For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.
117 | - For many-to-many bidirectional relationships, either side may be the owning side.
118 |
119 | Entities that use relationships often have dependencies on the existence of the other entity in the relationship. For example, a line item is part of an order; if the order is deleted, the line item also should be deleted. This is called a cascade delete relationship.
120 | The javax.persistence.CascadeType enumerated type defines the cascade operations that are applied in the cascade element of the relationship annotations. Table 32-1 lists the cascade operations for entities.
121 |
122 | Embeddable classes have the same rules as entity classes but are annotated with the javax.persistence.Embeddable annotation instead of @Entity.
123 |
124 | The following embeddable class, ZipCode, has the fields zip and plusFour:
125 |
126 | @Embeddable
127 | public class ZipCode {
128 | String zip;
129 | String plusFour;
130 | ...
131 | }
132 | This embeddable class is used by the Address entity:
133 |
134 | @Entity
135 | public class Address {
136 | @Id
137 | protected long id
138 | String street1;
139 | String street2;
140 | String city;
141 | String province;
142 | @Embedded
143 | ZipCode zipCode;
144 | String country;
145 | ...
146 | }
147 |
148 |
149 | You can configure how the Java Persistence provider maps inherited entities to the underlying datastore by decorating the root class of the hierarchy with the annotation javax.persistence.Inheritance. The following mapping strategies are used to map the entity data to the underlying database:
150 |
151 | A single table per class hierarchy
152 |
153 | A table per concrete entity class
154 |
155 | A “join” strategy, whereby fields or properties that are specific to a subclass are mapped to a different table than the fields or properties that are common to the parent class
156 |
157 |
158 | The Java Persistence API provides the following methods for querying entities.
159 |
160 | The Java Persistence query language (JPQL) is a simple, string-based language similar to SQL used to query entities and their relationships. See Chapter 34, The Java Persistence Query Language for more information.
161 |
162 | The Criteria API is used to create typesafe queries using Java programming language APIs to query for entities and their relationships. See Chapter 35, Using the Criteria API to Create Queries for more information.
163 |
164 | Both JPQL and the Criteria API have advantages and disadvantages.
165 |
166 | Just a few lines long, JPQL queries are typically more concise and more readable than Criteria queries. Developers familiar with SQL will find it easy to learn the syntax of JPQL. JPQL named queries can be defined in the entity class using a Java programming language annotation or in the application’s deployment descriptor. JPQL queries are not typesafe, however, and require a cast when retrieving the query result from the entity manager. This means that type-casting errors may not be caught at compile time. JPQL queries don’t support open-ended parameters.
167 |
168 | Criteria queries allow you to define the query in the business tier of the application. Although this is also possible using JPQL dynamic queries, Criteria queries provide better performance because JPQL dynamic queries must be parsed each time they are called. Criteria queries are typesafe and therefore don’t require casting, as JPQL queries do. The Criteria API is just another Java programming language API and doesn’t require developers to learn the syntax of another query language. Criteria queries are typically more verbose than JPQL queries and require the developer to create several objects and perform operations on those objects before submitting the query to the entity manager.
169 | ```
170 | src\main\java\com\in28minutes\hibernate\model\Passport.java
171 | ```
172 | package com.in28minutes.hibernate.model;
173 |
174 | import javax.persistence.Column;
175 | import javax.persistence.Entity;
176 | import javax.persistence.GeneratedValue;
177 | import javax.persistence.GenerationType;
178 | import javax.persistence.Id;
179 |
180 | @Entity
181 | public class Passport {
182 | @Id
183 | @GeneratedValue(strategy = GenerationType.IDENTITY)
184 | private long id;
185 |
186 | private String number;
187 |
188 | @Column(name = "issued_country")
189 | private String issuedCountry;
190 |
191 | public Passport() {
192 | super();
193 | }
194 |
195 | public Passport(long id, String number, String issuedCountry) {
196 | super();
197 | this.id = id;
198 | this.number = number;
199 | this.issuedCountry = issuedCountry;
200 | }
201 |
202 | public long getId() {
203 | return id;
204 | }
205 |
206 | public void setId(long id) {
207 | this.id = id;
208 | }
209 |
210 | public String getNumber() {
211 | return number;
212 | }
213 |
214 | public void setNumber(String number) {
215 | this.number = number;
216 | }
217 |
218 | public String getIssuedCountry() {
219 | return issuedCountry;
220 | }
221 |
222 | public void setIssuedCountry(String issuedCountry) {
223 | this.issuedCountry = issuedCountry;
224 | }
225 |
226 | @Override
227 | public String toString() {
228 | return "Passport [id=" + id + ", number=" + number + ", issuedCountry=" + issuedCountry + "] ";
229 | }
230 | }
231 | ```
232 | src\main\java\com\in28minutes\hibernate\model\Project.java
233 | ```
234 | package com.in28minutes.hibernate.model;
235 |
236 | public class Project {
237 | private int id;
238 | private String name;
239 |
240 | public int getId() {
241 | return id;
242 | }
243 |
244 | public void setId(int id) {
245 | this.id = id;
246 | }
247 |
248 | public String getName() {
249 | return name;
250 | }
251 |
252 | public void setName(String name) {
253 | this.name = name;
254 | }
255 |
256 | @Override
257 | public String toString() {
258 | return "Project [id=" + id + ", name=" + name + "]";
259 | }
260 | }
261 | ```
262 | src\main\java\com\in28minutes\hibernate\model\Student.java
263 | ```
264 | package com.in28minutes.hibernate.model;
265 |
266 | import javax.persistence.Entity;
267 | import javax.persistence.GeneratedValue;
268 | import javax.persistence.GenerationType;
269 | import javax.persistence.Id;
270 | import javax.persistence.NamedQuery;
271 | import javax.persistence.OneToOne;
272 | import javax.persistence.Table;
273 |
274 | @Entity
275 | @Table(name = "Student")
276 | @NamedQuery(query = "select s from Student s", name = "find all students")
277 | public class Student {
278 |
279 | @Id
280 | @GeneratedValue(strategy = GenerationType.IDENTITY)
281 | private long id;
282 |
283 | private String name;
284 |
285 | @OneToOne
286 | private Passport passport;
287 |
288 | private String email;
289 |
290 | public long getId() {
291 | return id;
292 | }
293 |
294 | public void setId(long id) {
295 | this.id = id;
296 | }
297 |
298 | public String getName() {
299 | return name;
300 | }
301 |
302 | public void setName(String name) {
303 | this.name = name;
304 | }
305 |
306 | public Passport getPassport() {
307 | return passport;
308 | }
309 |
310 | public void setPassportId(Passport passport) {
311 | this.passport = passport;
312 | }
313 |
314 | public String getEmail() {
315 | return email;
316 | }
317 |
318 | public void setEmail(String email) {
319 | this.email = email;
320 | }
321 |
322 | @Override
323 | public String toString() {
324 | return "Student [id=" + id + ", name=" + name + ", passport=" + passport + ", email=" + email + "]";
325 | }
326 |
327 | }
328 | ```
329 | src\main\java\com\in28minutes\hibernate\model\Task.java
330 | ```
331 | package com.in28minutes.hibernate.model;
332 |
333 | import java.util.Date;
334 |
335 | public class Task {
336 | private int id;
337 | private int projectId;
338 | private Date startDate;
339 | private String desc;
340 |
341 | public int getId() {
342 | return id;
343 | }
344 |
345 | public void setId(int id) {
346 | this.id = id;
347 | }
348 |
349 | public int getProjectId() {
350 | return projectId;
351 | }
352 |
353 | public void setProjectId(int projectId) {
354 | this.projectId = projectId;
355 | }
356 |
357 | public Date getStartDate() {
358 | return startDate;
359 | }
360 |
361 | public void setStartDate(Date startDate) {
362 | this.startDate = startDate;
363 | }
364 |
365 | public String getDesc() {
366 | return desc;
367 | }
368 |
369 | public void setDesc(String desc) {
370 | this.desc = desc;
371 | }
372 |
373 | @Override
374 | public String toString() {
375 | return "Task [id=" + id + ", projectId=" + projectId + ", startDate=" + startDate + ", desc=" + desc + "]";
376 | }
377 |
378 | }
379 | ```
380 | src\main\java\com\in28minutes\hibernate\service\StudentRepository.java
381 | ```
382 | package com.in28minutes.hibernate.service;
383 |
384 | import java.util.List;
385 |
386 | import javax.persistence.EntityManager;
387 | import javax.persistence.PersistenceContext;
388 | import javax.persistence.Query;
389 |
390 | import org.springframework.stereotype.Repository;
391 |
392 | import com.in28minutes.hibernate.model.Student;
393 |
394 | @Repository
395 | public class StudentRepository {
396 |
397 | @PersistenceContext
398 | private EntityManager entityManager;
399 |
400 | public Student getStudent(final long id) {
401 | return entityManager.find(Student.class, id);
402 | }
403 |
404 | public Student insertStudent(Student student) {
405 | if (student.getPassport() != null)
406 | entityManager.merge(student.getPassport());
407 | return entityManager.merge(student);
408 | }
409 |
410 | public Student updateStudent(Student student) {
411 | entityManager.merge(student);
412 | return student;
413 | }
414 |
415 | public Student retrieveStudentsFrom(String string) {
416 | return null;
417 | }
418 |
419 | public List getAllStudents() {
420 | Query query = entityManager.createNamedQuery("find all students");
421 | return query.getResultList();
422 | }
423 | }
424 | ```
425 | src\main\java\com\in28minutes\hibernate\service\StudentService.java
426 | ```
427 | package com.in28minutes.hibernate.service;
428 |
429 | import java.util.List;
430 |
431 | import javax.transaction.Transactional;
432 |
433 | import org.springframework.beans.factory.annotation.Autowired;
434 | import org.springframework.stereotype.Service;
435 |
436 | import com.in28minutes.hibernate.model.Student;
437 |
438 | @Service
439 | public class StudentService {
440 |
441 | @Autowired
442 | StudentRepository service;
443 |
444 | @Transactional
445 | public Student insertStudent(Student student) {
446 | return service.insertStudent(student);
447 | }
448 |
449 | @Transactional
450 | public Student getStudent(final long id) {
451 | return service.getStudent(id);
452 | }
453 |
454 | @Transactional
455 | public Student updateStudent(Student student) {
456 | return service.updateStudent(student);
457 | }
458 |
459 | @Transactional
460 | public Student retrieveIndianStudents() {
461 | return service.retrieveStudentsFrom("India");
462 | }
463 |
464 | @Transactional
465 | public List getAllStudents() {
466 | return service.getAllStudents();
467 | }
468 |
469 | }
470 | ```
471 | src\main\resources\config\data.sql
472 | ```
473 | INSERT INTO passport VALUES (201,'L1234567','India');
474 | INSERT INTO passport VALUES (202,'L1234568','India');
475 |
476 | INSERT INTO student VALUES (101,201,'Jane', 'jane@doe.com');
477 | INSERT INTO student VALUES (102,202,'Doe', 'doe@doe.com');
478 |
479 | INSERT into project VALUES (301, 'In28Minutes Project 1');
480 |
481 | INSERT into task VALUES (401, 301, 'Create JPA Tutorial','2015-12-24');
482 |
483 | INSERT into student_project VALUES (501, 101, 301, 401);
484 | ```
485 | src\main\resources\config\database.properties
486 | ```
487 | #HSQL in-memory db
488 | db.driver=org.hsqldb.jdbcDriver
489 | db.url=jdbc:hsqldb:mem:firstdb
490 | db.username=sa
491 | db.password=
492 | ```
493 | src\main\resources\config\hibernate.properties
494 | ```
495 | hibernate.dialect=org.hibernate.dialect.HSQLDialect
496 | hibernate.show_sql=false
497 | hibernate.format_sql=false
498 | hibernate.use_sql_comments=true
499 | ```
500 | src\main\resources\config\schema.sql
501 | ```
502 | CREATE TABLE student (
503 | id int IDENTITY NOT NULL PRIMARY KEY,
504 | passport_id int NULL,
505 | name varchar(32) NOT NULL,
506 | email varchar(32) NOT NULL
507 | );
508 |
509 | CREATE TABLE passport (
510 | id int IDENTITY NOT NULL PRIMARY KEY,
511 | number varchar(32) NOT NULL,
512 | issued_country varchar(32) NOT NULL
513 | );
514 |
515 | alter table student add constraint student_passport_fk foreign key (passport_id) references passport(id);
516 |
517 |
518 | CREATE TABLE project (
519 | id int IDENTITY NOT NULL PRIMARY KEY,
520 | name varchar(32) NOT NULL
521 | );
522 |
523 | CREATE TABLE task (
524 | id int IDENTITY NOT NULL PRIMARY KEY,
525 | project_id int NOT NULL,
526 | desc varchar(216) NOT NULL,
527 | start_date date DEFAULT NULL
528 | );
529 |
530 | alter table task add constraint task_project_fk foreign key (project_id) references project(id);
531 |
532 | CREATE TABLE student_project (
533 | id int IDENTITY NOT NULL PRIMARY KEY,
534 | student_id int NOT NULL,
535 | project_id int NOT NULL,
536 | task_id int NOT NULL
537 | );
538 |
539 | alter table student_project add constraint student_project_student_fk foreign key (student_id) references student(id);
540 | alter table student_project add constraint student_project_project_fk foreign key (project_id) references project(id);
541 | alter table student_project add constraint student_project_task_fk foreign key (task_id) references task(id);
542 | ```
543 | src\main\resources\log4j.properties
544 | ```
545 | log4j.rootLogger=info, stdout
546 |
547 | #log messages to stdout
548 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
549 | log4j.appender.stdout.Target=System.out
550 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
551 | log4j.appender.stdout.layout.ConversionPattern= %d{dd/MM/yyyy HH:mm} [%-5p] %c:%L - %m%n
552 |
553 | # Log everything. Good for troubleshooting
554 | log4j.logger.org.hibernate=debug
555 | log4j.logger.org.springframework=debug
556 | log4j.javax.servlet=info
557 |
558 | # Log all JDBC parameters
559 | log4j.logger.org.hibernate.type=all
560 | ```
561 | src\main\resources\META-INF\persistence.xml
562 | ```
563 |
564 |
565 |
567 |
568 | org.hibernate.jpa.HibernatePersistenceProvider
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 | ```
579 | src\main\resources\META-INF\spring\spring-context.xml
580 | ```
581 |
582 |
583 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 | ```
637 | src\test\java\com\in28minutes\hibernate\service\StudentServiceTest.java
638 | ```
639 | package com.in28minutes.hibernate.service;
640 |
641 | import static org.junit.Assert.assertEquals;
642 | import static org.junit.Assert.assertNotNull;
643 |
644 | import org.junit.After;
645 | import org.junit.Test;
646 | import org.junit.runner.RunWith;
647 | import org.springframework.beans.factory.annotation.Autowired;
648 | import org.springframework.stereotype.Service;
649 | import org.springframework.test.context.ContextConfiguration;
650 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
651 | import org.springframework.transaction.annotation.Transactional;
652 |
653 | import com.in28minutes.hibernate.model.Passport;
654 | import com.in28minutes.hibernate.model.Student;
655 |
656 | @RunWith(SpringJUnit4ClassRunner.class)
657 | @ContextConfiguration(locations = { "classpath:META-INF/spring/spring-context.xml" })
658 | @Service
659 | public class StudentServiceTest {
660 |
661 | @Autowired
662 | private StudentService service;
663 |
664 | @Test
665 | @Transactional
666 | public void testGetStudent() {
667 | Student student = service.getStudent(101);
668 | System.out.println(student);
669 | assertNotNull(student);
670 | assertEquals(101, student.getId());
671 | }
672 |
673 | @Test
674 | @Transactional
675 | public void testGetStudent_GettingAPassport() {
676 | Student student = service.getStudent(101);
677 | assertNotNull(student.getPassport());
678 | assertEquals(201, student.getPassport().getId());
679 | }
680 |
681 | @Test
682 | @Transactional
683 | public void testUpdateStudent() {
684 | Student student = service.getStudent(101);
685 | student.setName("Doe v2");
686 | Student insertedStudent = service.updateStudent(student);
687 | Student retrievedStudent = service.getStudent(insertedStudent.getId());
688 | System.out.println(student);
689 | assertNotNull(retrievedStudent);
690 | }
691 |
692 | @Test
693 | public void testInsertStudent() {
694 | Passport passport = new Passport(202, "L12344432", "India");
695 | Student student = createStudent("dummy@dummy.com", "Doe", passport);
696 | Student insertedStudent = service.insertStudent(student);
697 | Student retrievedStudent = service.getStudent(insertedStudent.getId());
698 | assertNotNull(retrievedStudent);
699 | }
700 |
701 | @Test
702 | public void testInsertStudent_withoutPassport() {
703 | Student student = createStudent("dummy@dummy.com", "Doe", null);
704 | Student insertedStudent = service.insertStudent(student);
705 | Student retrievedStudent = service.getStudent(insertedStudent.getId());
706 | assertNotNull(retrievedStudent);
707 | }
708 |
709 | private Student createStudent(String email, String name, Passport passport) {
710 | Student student = new Student();
711 | student.setEmail(email);
712 | student.setName(name);
713 | student.setPassportId(passport);
714 | return student;
715 | }
716 |
717 | @After
718 | public void printAllDataAfterTest() {
719 | System.out.println(service.getAllStudents());
720 | }
721 | }
722 | ```
723 |
--------------------------------------------------------------------------------
/jdbc-to-spring-jdbc-to-jpa.md:
--------------------------------------------------------------------------------
1 | \mvnw
2 | ```
3 | #!/bin/sh
4 | # ----------------------------------------------------------------------------
5 | # Licensed to the Apache Software Foundation (ASF) under one
6 | # or more contributor license agreements. See the NOTICE file
7 | # distributed with this work for additional information
8 | # regarding copyright ownership. The ASF licenses this file
9 | # to you under the Apache License, Version 2.0 (the
10 | # "License"); you may not use this file except in compliance
11 | # with the License. You may obtain a copy of the License at
12 | #
13 | # http://www.apache.org/licenses/LICENSE-2.0
14 | #
15 | # Unless required by applicable law or agreed to in writing,
16 | # software distributed under the License is distributed on an
17 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 | # KIND, either express or implied. See the License for the
19 | # specific language governing permissions and limitations
20 | # under the License.
21 | # ----------------------------------------------------------------------------
22 |
23 | # ----------------------------------------------------------------------------
24 | # Maven2 Start Up Batch script
25 | #
26 | # Required ENV vars:
27 | # ------------------
28 | # JAVA_HOME - location of a JDK home dir
29 | #
30 | # Optional ENV vars
31 | # -----------------
32 | # M2_HOME - location of maven2's installed home dir
33 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
34 | # e.g. to debug Maven itself, use
35 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
36 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
37 | # ----------------------------------------------------------------------------
38 |
39 | if [ -z "$MAVEN_SKIP_RC" ] ; then
40 |
41 | if [ -f /etc/mavenrc ] ; then
42 | . /etc/mavenrc
43 | fi
44 |
45 | if [ -f "$HOME/.mavenrc" ] ; then
46 | . "$HOME/.mavenrc"
47 | fi
48 |
49 | fi
50 |
51 | # OS specific support. $var _must_ be set to either true or false.
52 | cygwin=false;
53 | darwin=false;
54 | mingw=false
55 | case "`uname`" in
56 | CYGWIN*) cygwin=true ;;
57 | MINGW*) mingw=true;;
58 | Darwin*) darwin=true
59 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
60 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
61 | if [ -z "$JAVA_HOME" ]; then
62 | if [ -x "/usr/libexec/java_home" ]; then
63 | export JAVA_HOME="`/usr/libexec/java_home`"
64 | else
65 | export JAVA_HOME="/Library/Java/Home"
66 | fi
67 | fi
68 | ;;
69 | esac
70 |
71 | if [ -z "$JAVA_HOME" ] ; then
72 | if [ -r /etc/gentoo-release ] ; then
73 | JAVA_HOME=`java-config --jre-home`
74 | fi
75 | fi
76 |
77 | if [ -z "$M2_HOME" ] ; then
78 | ## resolve links - $0 may be a link to maven's home
79 | PRG="$0"
80 |
81 | # need this for relative symlinks
82 | while [ -h "$PRG" ] ; do
83 | ls=`ls -ld "$PRG"`
84 | link=`expr "$ls" : '.*-> \(.*\)$'`
85 | if expr "$link" : '/.*' > /dev/null; then
86 | PRG="$link"
87 | else
88 | PRG="`dirname "$PRG"`/$link"
89 | fi
90 | done
91 |
92 | saveddir=`pwd`
93 |
94 | M2_HOME=`dirname "$PRG"`/..
95 |
96 | # make it fully qualified
97 | M2_HOME=`cd "$M2_HOME" && pwd`
98 |
99 | cd "$saveddir"
100 | # echo Using m2 at $M2_HOME
101 | fi
102 |
103 | # For Cygwin, ensure paths are in UNIX format before anything is touched
104 | if $cygwin ; then
105 | [ -n "$M2_HOME" ] &&
106 | M2_HOME=`cygpath --unix "$M2_HOME"`
107 | [ -n "$JAVA_HOME" ] &&
108 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
109 | [ -n "$CLASSPATH" ] &&
110 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
111 | fi
112 |
113 | # For Migwn, ensure paths are in UNIX format before anything is touched
114 | if $mingw ; then
115 | [ -n "$M2_HOME" ] &&
116 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
117 | [ -n "$JAVA_HOME" ] &&
118 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
119 | # TODO classpath?
120 | fi
121 |
122 | if [ -z "$JAVA_HOME" ]; then
123 | javaExecutable="`which javac`"
124 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
125 | # readlink(1) is not available as standard on Solaris 10.
126 | readLink=`which readlink`
127 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
128 | if $darwin ; then
129 | javaHome="`dirname \"$javaExecutable\"`"
130 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
131 | else
132 | javaExecutable="`readlink -f \"$javaExecutable\"`"
133 | fi
134 | javaHome="`dirname \"$javaExecutable\"`"
135 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
136 | JAVA_HOME="$javaHome"
137 | export JAVA_HOME
138 | fi
139 | fi
140 | fi
141 |
142 | if [ -z "$JAVACMD" ] ; then
143 | if [ -n "$JAVA_HOME" ] ; then
144 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
145 | # IBM's JDK on AIX uses strange locations for the executables
146 | JAVACMD="$JAVA_HOME/jre/sh/java"
147 | else
148 | JAVACMD="$JAVA_HOME/bin/java"
149 | fi
150 | else
151 | JAVACMD="`which java`"
152 | fi
153 | fi
154 |
155 | if [ ! -x "$JAVACMD" ] ; then
156 | echo "Error: JAVA_HOME is not defined correctly." >&2
157 | echo " We cannot execute $JAVACMD" >&2
158 | exit 1
159 | fi
160 |
161 | if [ -z "$JAVA_HOME" ] ; then
162 | echo "Warning: JAVA_HOME environment variable is not set."
163 | fi
164 |
165 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
166 |
167 | # traverses directory structure from process work directory to filesystem root
168 | # first directory with .mvn subdirectory is considered project base directory
169 | find_maven_basedir() {
170 |
171 | if [ -z "$1" ]
172 | then
173 | echo "Path not specified to find_maven_basedir"
174 | return 1
175 | fi
176 |
177 | basedir="$1"
178 | wdir="$1"
179 | while [ "$wdir" != '/' ] ; do
180 | if [ -d "$wdir"/.mvn ] ; then
181 | basedir=$wdir
182 | break
183 | fi
184 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
185 | if [ -d "${wdir}" ]; then
186 | wdir=`cd "$wdir/.."; pwd`
187 | fi
188 | # end of workaround
189 | done
190 | echo "${basedir}"
191 | }
192 |
193 | # concatenates all lines of a file
194 | concat_lines() {
195 | if [ -f "$1" ]; then
196 | echo "$(tr -s '\n' ' ' < "$1")"
197 | fi
198 | }
199 |
200 | BASE_DIR=`find_maven_basedir "$(pwd)"`
201 | if [ -z "$BASE_DIR" ]; then
202 | exit 1;
203 | fi
204 |
205 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
206 | echo $MAVEN_PROJECTBASEDIR
207 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
208 |
209 | # For Cygwin, switch paths to Windows format before running java
210 | if $cygwin; then
211 | [ -n "$M2_HOME" ] &&
212 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
213 | [ -n "$JAVA_HOME" ] &&
214 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
215 | [ -n "$CLASSPATH" ] &&
216 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
217 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
218 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
219 | fi
220 |
221 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
222 |
223 | exec "$JAVACMD" \
224 | $MAVEN_OPTS \
225 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
226 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
227 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
228 | ```
229 | \mvnw.cmd
230 | ```
231 | @REM ----------------------------------------------------------------------------
232 | @REM Licensed to the Apache Software Foundation (ASF) under one
233 | @REM or more contributor license agreements. See the NOTICE file
234 | @REM distributed with this work for additional information
235 | @REM regarding copyright ownership. The ASF licenses this file
236 | @REM to you under the Apache License, Version 2.0 (the
237 | @REM "License"); you may not use this file except in compliance
238 | @REM with the License. You may obtain a copy of the License at
239 | @REM
240 | @REM http://www.apache.org/licenses/LICENSE-2.0
241 | @REM
242 | @REM Unless required by applicable law or agreed to in writing,
243 | @REM software distributed under the License is distributed on an
244 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
245 | @REM KIND, either express or implied. See the License for the
246 | @REM specific language governing permissions and limitations
247 | @REM under the License.
248 | @REM ----------------------------------------------------------------------------
249 |
250 | @REM ----------------------------------------------------------------------------
251 | @REM Maven2 Start Up Batch script
252 | @REM
253 | @REM Required ENV vars:
254 | @REM JAVA_HOME - location of a JDK home dir
255 | @REM
256 | @REM Optional ENV vars
257 | @REM M2_HOME - location of maven2's installed home dir
258 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
259 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
260 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
261 | @REM e.g. to debug Maven itself, use
262 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
263 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
264 | @REM ----------------------------------------------------------------------------
265 |
266 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
267 | @echo off
268 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
269 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
270 |
271 | @REM set %HOME% to equivalent of $HOME
272 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
273 |
274 | @REM Execute a user defined script before this one
275 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
276 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
277 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
278 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
279 | :skipRcPre
280 |
281 | @setlocal
282 |
283 | set ERROR_CODE=0
284 |
285 | @REM To isolate internal variables from possible post scripts, we use another setlocal
286 | @setlocal
287 |
288 | @REM ==== START VALIDATION ====
289 | if not "%JAVA_HOME%" == "" goto OkJHome
290 |
291 | echo.
292 | echo Error: JAVA_HOME not found in your environment. >&2
293 | echo Please set the JAVA_HOME variable in your environment to match the >&2
294 | echo location of your Java installation. >&2
295 | echo.
296 | goto error
297 |
298 | :OkJHome
299 | if exist "%JAVA_HOME%\bin\java.exe" goto init
300 |
301 | echo.
302 | echo Error: JAVA_HOME is set to an invalid directory. >&2
303 | echo JAVA_HOME = "%JAVA_HOME%" >&2
304 | echo Please set the JAVA_HOME variable in your environment to match the >&2
305 | echo location of your Java installation. >&2
306 | echo.
307 | goto error
308 |
309 | @REM ==== END VALIDATION ====
310 |
311 | :init
312 |
313 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
314 | @REM Fallback to current working directory if not found.
315 |
316 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
317 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
318 |
319 | set EXEC_DIR=%CD%
320 | set WDIR=%EXEC_DIR%
321 | :findBaseDir
322 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
323 | cd ..
324 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
325 | set WDIR=%CD%
326 | goto findBaseDir
327 |
328 | :baseDirFound
329 | set MAVEN_PROJECTBASEDIR=%WDIR%
330 | cd "%EXEC_DIR%"
331 | goto endDetectBaseDir
332 |
333 | :baseDirNotFound
334 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
335 | cd "%EXEC_DIR%"
336 |
337 | :endDetectBaseDir
338 |
339 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
340 |
341 | @setlocal EnableExtensions EnableDelayedExpansion
342 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
343 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
344 |
345 | :endReadAdditionalConfig
346 |
347 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
348 |
349 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
350 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
351 |
352 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
353 | if ERRORLEVEL 1 goto error
354 | goto end
355 |
356 | :error
357 | set ERROR_CODE=1
358 |
359 | :end
360 | @endlocal & set ERROR_CODE=%ERROR_CODE%
361 |
362 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
363 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
364 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
365 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
366 | :skipRcPost
367 |
368 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
369 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
370 |
371 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
372 |
373 | exit /B %ERROR_CODE%
374 | ```
375 | \pom.xml
376 | ```xml
377 |
378 |
380 | 4.0.0
381 |
382 | com.example
383 | jdbc-demo
384 | 0.0.1-SNAPSHOT
385 | jar
386 |
387 | demo
388 | Demo project for Spring Boot
389 |
390 |
391 | org.springframework.boot
392 | spring-boot-starter-parent
393 | 1.5.3.RELEASE
394 |
395 |
396 |
397 |
398 | UTF-8
399 | UTF-8
400 | 1.8
401 |
402 |
403 |
404 |
405 | org.springframework.boot
406 | spring-boot-starter-jdbc
407 |
408 |
409 |
410 |
411 | com.h2database
412 | h2
413 |
414 |
415 |
416 | org.springframework.boot
417 | spring-boot-starter-web
418 |
419 |
420 |
421 | org.mybatis.spring.boot
422 | mybatis-spring-boot-starter
423 | 1.2.1
424 |
425 |
426 |
427 | org.springframework.boot
428 | spring-boot-starter-data-jpa
429 |
430 |
431 |
432 | org.springframework.boot
433 | spring-boot-starter-test
434 | test
435 |
436 |
437 |
438 |
439 |
440 |
441 | org.springframework.boot
442 | spring-boot-maven-plugin
443 |
444 |
445 |
446 |
447 |
448 |
449 | spring-snapshots
450 | Spring Snapshots
451 | https://repo.spring.io/snapshot
452 |
453 | true
454 |
455 |
456 |
457 | spring-milestones
458 | Spring Milestones
459 | https://repo.spring.io/milestone
460 |
461 | false
462 |
463 |
464 |
465 |
466 |
467 |
468 | spring-snapshots
469 | Spring Snapshots
470 | https://repo.spring.io/snapshot
471 |
472 | true
473 |
474 |
475 |
476 | spring-milestones
477 | Spring Milestones
478 | https://repo.spring.io/milestone
479 |
480 | false
481 |
482 |
483 |
484 |
485 |
486 |
487 | ```
488 | \src\main\java\com\example\demo\data\student\GenericAllPurposeRepository.java
489 | ```java
490 | package com.example.demo.data.student;
491 |
492 | import javax.persistence.EntityManager;
493 | import javax.persistence.PersistenceContext;
494 | import javax.transaction.Transactional;
495 |
496 | import org.springframework.stereotype.Repository;
497 |
498 | import com.example.demo.entity.Passport;
499 | import com.example.demo.entity.Project;
500 | import com.example.demo.entity.Student;
501 | import com.example.demo.entity.Task;
502 |
503 | @Repository
504 | @Transactional
505 | public class GenericAllPurposeRepository {
506 |
507 | @PersistenceContext
508 | private EntityManager entityManager;
509 |
510 | public Passport getPassport(final long id) {
511 | Passport passport = entityManager
512 | .find(Passport.class, id);
513 | passport.getStudent();
514 | return passport;
515 | }
516 |
517 | public Task createTask(Task task) {
518 | return entityManager.merge(task);
519 | }
520 |
521 | public Project createProject(Project project) {
522 | return entityManager.merge(project);
523 | }
524 |
525 | public Student createStudent(Student student) {
526 | return entityManager.merge(student);
527 | }
528 |
529 | public void assignStudentToProject(long studentId, long projectId) {
530 | Project project = entityManager.find(Project.class,
531 | projectId);
532 | Student student = entityManager.find(Student.class,
533 | studentId);
534 | project.getStudents().add(student);
535 | }
536 |
537 | }
538 | ```
539 | \src\main\java\com\example\demo\data\student\StudentRepository.java
540 | ```java
541 | package com.example.demo.data.student;
542 |
543 | import java.util.List;
544 |
545 | import javax.persistence.EntityManager;
546 | import javax.persistence.PersistenceContext;
547 | import javax.persistence.Query;
548 | import javax.transaction.Transactional;
549 |
550 | import org.springframework.stereotype.Repository;
551 |
552 | import com.example.demo.entity.Student;
553 |
554 | @Repository
555 | @Transactional
556 | public class StudentRepository {
557 |
558 | @PersistenceContext
559 | private EntityManager entityManager;
560 |
561 | public Student retrieveStudent(final long id) {
562 | return entityManager.find(Student.class, id);
563 | }
564 |
565 | public Student createStudent(Student student) {
566 | if (student.getPassport() != null)
567 | entityManager.merge(student.getPassport());
568 | return entityManager.merge(student);
569 | }
570 |
571 | public Student updateStudent(Student student) {
572 | entityManager.merge(student);
573 | return student;
574 | }
575 |
576 | public Student retrieveStudentsFrom(String string) {
577 | return null;
578 | }
579 |
580 | public List retrieveAllStudents() {
581 | Query query = entityManager
582 | .createNamedQuery("find all students");
583 | return query.getResultList();
584 | }
585 | }
586 | ```
587 | \src\main\java\com\example\demo\data\todo\TodoDataService.java
588 | ```java
589 | package com.example.demo.data.todo;
590 |
591 | import java.sql.SQLException;
592 | import java.util.Date;
593 | import java.util.List;
594 |
595 | import com.example.demo.entity.Todo;
596 |
597 | public interface TodoDataService {
598 |
599 | public List retrieveTodos(String user)
600 | throws SQLException;
601 |
602 | public int addTodo(String user, String desc,
603 | Date targetDate, boolean isDone)
604 | throws SQLException;
605 |
606 | public Todo retrieveTodo(int id) throws SQLException;
607 |
608 | public void updateTodo(Todo todo) throws SQLException;
609 |
610 | public void deleteTodo(int id) throws SQLException;
611 | }
612 | ```
613 | \src\main\java\com\example\demo\data\todo\TodoJdbcService.java
614 | ```java
615 | package com.example.demo.data.todo;
616 |
617 | import java.sql.Connection;
618 | import java.sql.PreparedStatement;
619 | import java.sql.ResultSet;
620 | import java.sql.SQLException;
621 | import java.sql.Statement;
622 | import java.sql.Timestamp;
623 | import java.util.ArrayList;
624 | import java.util.Date;
625 | import java.util.List;
626 |
627 | import javax.sql.DataSource;
628 |
629 | import org.springframework.beans.factory.annotation.Autowired;
630 | import org.springframework.stereotype.Component;
631 |
632 | import com.example.demo.entity.Todo;
633 |
634 | @Component
635 | public class TodoJdbcService implements TodoDataService {
636 |
637 | @Autowired
638 | DataSource datasource;
639 |
640 | // Think about exception handling
641 | // We are explicitly getting the connection! What if there is an
642 | // exception while executing the query!
643 |
644 | @Override
645 | public List retrieveTodos(String user)
646 | throws SQLException {
647 | Connection connection = datasource.getConnection();
648 |
649 | PreparedStatement st = connection.prepareStatement(
650 | "SELECT * FROM TODO where user=?");
651 |
652 | st.setString(1, user);
653 |
654 | ResultSet resultSet = st.executeQuery();
655 | List todos = new ArrayList<>();
656 |
657 | while (resultSet.next()) {
658 |
659 | Todo todo = new Todo(resultSet.getInt("id"),
660 | resultSet.getString("user"),
661 | resultSet.getString("desc"),
662 | resultSet.getTimestamp("target_date"),
663 | resultSet.getBoolean("is_done"));
664 | todos.add(todo);
665 | }
666 |
667 | st.close();
668 |
669 | connection.close();
670 |
671 | return todos;
672 |
673 | }
674 |
675 | @Override
676 | public int addTodo(String user, String desc,
677 | Date targetDate, boolean isDone)
678 | throws SQLException {
679 | Connection connection = datasource.getConnection();
680 |
681 | PreparedStatement st = connection.prepareStatement(
682 | "INSERT INTO todo(user, desc, target_date, is_done) VALUES (?,?,?,?)",
683 | Statement.RETURN_GENERATED_KEYS);
684 |
685 | st.setString(1, user);
686 | st.setString(2, desc);
687 | st.setTimestamp(3,
688 | new Timestamp(targetDate.getTime()));
689 | st.setBoolean(4, isDone);
690 |
691 | int id = st.executeUpdate();
692 |
693 | st.close();
694 |
695 | connection.close();
696 |
697 | return id;
698 |
699 | }
700 |
701 | @Override
702 | public Todo retrieveTodo(int id) throws SQLException {
703 | Connection connection = datasource.getConnection();
704 |
705 | PreparedStatement st = connection.prepareStatement(
706 | "SELECT * FROM TODO where id=?");
707 |
708 | st.setInt(1, id);
709 |
710 | ResultSet resultSet = st.executeQuery();
711 |
712 | Todo todo = null;
713 |
714 | if (resultSet.next()) {
715 |
716 | todo = new Todo(resultSet.getInt("id"),
717 | resultSet.getString("user"),
718 | resultSet.getString("desc"),
719 | resultSet.getTimestamp("target_date"),
720 | resultSet.getBoolean("is_done"));
721 |
722 | }
723 |
724 | st.close();
725 |
726 | connection.close();
727 |
728 | return todo;
729 |
730 | }
731 |
732 | @Override
733 | public void updateTodo(Todo todo) throws SQLException {
734 | Connection connection = datasource.getConnection();
735 |
736 | PreparedStatement st = connection.prepareStatement(
737 | "Update todo set user=?, desc=?, target_date=?, is_done=? where id=?");
738 |
739 | st.setString(1, todo.getUser());
740 | st.setString(2, todo.getDesc());
741 | st.setTimestamp(3, new Timestamp(
742 | todo.getTargetDate().getTime()));
743 | st.setBoolean(4, todo.isDone());
744 | st.setInt(5, todo.getId());
745 |
746 | st.execute();
747 |
748 | st.close();
749 |
750 | connection.close();
751 |
752 | }
753 |
754 | @Override
755 | public void deleteTodo(int id) throws SQLException {
756 | Connection connection = datasource.getConnection();
757 |
758 | PreparedStatement st = connection.prepareStatement(
759 | "delete from todo where id=?");
760 |
761 | st.setInt(1, id);
762 |
763 | st.execute();
764 |
765 | st.close();
766 |
767 | connection.close();
768 |
769 | }
770 |
771 | }
772 | ```
773 | \src\main\java\com\example\demo\data\todo\TodoJPAService.java
774 | ```java
775 | package com.example.demo.data.todo;
776 |
777 | import java.util.Date;
778 | import java.util.List;
779 |
780 | import javax.persistence.EntityManager;
781 | import javax.persistence.PersistenceContext;
782 | import javax.persistence.Query;
783 | import javax.transaction.Transactional;
784 |
785 | import org.springframework.stereotype.Repository;
786 |
787 | import com.example.demo.entity.Todo;
788 |
789 | @Repository
790 | @Transactional
791 | public class TodoJPAService implements TodoDataService {
792 |
793 | @PersistenceContext
794 | private EntityManager entityManager;
795 |
796 | @Override
797 | public List retrieveTodos(String user) {
798 | Query query = entityManager.createNamedQuery(
799 | "find all todos for user", Todo.class);
800 | query.setParameter(1, user);
801 | return query.getResultList();
802 |
803 | }
804 |
805 | @Override
806 | public int addTodo(String user, String desc,
807 | Date targetDate, boolean isDone) {
808 | Todo todo = entityManager.merge(
809 | new Todo(user, desc, targetDate, isDone));
810 | return todo.getId();
811 | }
812 |
813 | @Override
814 | public Todo retrieveTodo(int id) {
815 | return entityManager.find(Todo.class, id);
816 | }
817 |
818 | @Override
819 | public void updateTodo(Todo todo) {
820 | entityManager.merge(todo);
821 | }
822 |
823 | @Override
824 | public void deleteTodo(int id) {
825 | Todo todo = retrieveTodo(id);
826 | entityManager.remove(todo);
827 | }
828 | }
829 | ```
830 | \src\main\java\com\example\demo\data\todo\TodoMybatisService.java
831 | ```java
832 | package com.example.demo.data.todo;
833 |
834 | import java.sql.SQLException;
835 | import java.util.Date;
836 | import java.util.List;
837 |
838 | import org.apache.ibatis.annotations.Delete;
839 | import org.apache.ibatis.annotations.Insert;
840 | import org.apache.ibatis.annotations.Mapper;
841 | import org.apache.ibatis.annotations.Param;
842 | import org.apache.ibatis.annotations.Select;
843 | import org.apache.ibatis.annotations.Update;
844 |
845 | import com.example.demo.entity.Todo;
846 |
847 | @Mapper
848 | public interface TodoMybatisService
849 | extends TodoDataService {
850 |
851 | @Override
852 | @Insert("INSERT INTO TODO(user, desc, target_date, is_done) VALUES (#{user}, #{desc}, #{targetDate}, #{isDone})")
853 | public int addTodo(@Param("user") String user,
854 | @Param("desc") String desc,
855 | @Param("targetDate") Date targetDate,
856 | @Param("isDone") boolean isDone)
857 | throws SQLException;
858 |
859 | @Override
860 | @Select("SELECT * FROM TODO WHERE id = #{id}")
861 | public Todo retrieveTodo(int id) throws SQLException;
862 |
863 | @Override
864 | @Update("Update todo set user=#{user}, desc=#{desc}, target_date=#{targetDate}, is_done=#{isDone} where id=#{id}")
865 | public void updateTodo(Todo todo) throws SQLException;
866 |
867 | @Override
868 | @Delete("DELETE FROM TODO WHERE id = #{id}")
869 | public void deleteTodo(int id);
870 |
871 | @Override
872 | @Select("SELECT * FROM TODO WHERE user = #{user}")
873 | List retrieveTodos(@Param("user") String user);
874 |
875 | }
876 | ```
877 | \src\main\java\com\example\demo\data\todo\TodoSpringJdbcService.java
878 | ```java
879 | package com.example.demo.data.todo;
880 |
881 | import java.sql.ResultSet;
882 | import java.sql.SQLException;
883 | import java.sql.Timestamp;
884 | import java.util.Date;
885 | import java.util.HashMap;
886 | import java.util.List;
887 | import java.util.Map;
888 |
889 | import javax.sql.DataSource;
890 |
891 | import org.springframework.beans.factory.annotation.Autowired;
892 | import org.springframework.jdbc.core.JdbcTemplate;
893 | import org.springframework.jdbc.core.RowMapper;
894 | import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
895 | import org.springframework.stereotype.Component;
896 |
897 | import com.example.demo.entity.Todo;
898 |
899 | @Component
900 | public class TodoSpringJdbcService
901 | implements TodoDataService {
902 |
903 | @Autowired
904 | JdbcTemplate jdbcTemplate;
905 |
906 | SimpleJdbcInsert insertTodo;
907 |
908 | @Autowired
909 | public void setDataSource(DataSource dataSource) {
910 | this.insertTodo = new SimpleJdbcInsert(dataSource)
911 | .withTableName("TODO")
912 | .usingGeneratedKeyColumns("id");
913 | }
914 |
915 | // new BeanPropertyRowMapper(TodoMapper.class)
916 | class TodoMapper implements RowMapper {
917 | @Override
918 | public Todo mapRow(ResultSet rs, int rowNum)
919 | throws SQLException {
920 | Todo todo = new Todo();
921 |
922 | todo.setId(rs.getInt("id"));
923 | todo.setUser(rs.getString("user"));
924 | todo.setDesc(rs.getString("desc"));
925 | todo.setTargetDate(
926 | rs.getTimestamp("target_date"));
927 | todo.setDone(rs.getBoolean("is_done"));
928 | return todo;
929 | }
930 | }
931 |
932 | @Override
933 | public List retrieveTodos(String user) {
934 | return jdbcTemplate.query(
935 | "SELECT * FROM TODO where user = ?",
936 | new Object[] { user }, new TodoMapper());
937 |
938 | }
939 |
940 | @Override
941 | public int addTodo(String user, String desc,
942 | Date targetDate, boolean isDone)
943 | throws SQLException {
944 | Map params = new HashMap();
945 | params.put("user", user);
946 | params.put("desc", desc);
947 | params.put("target_date", targetDate);
948 | params.put("is_done", isDone);
949 | Number id = insertTodo.executeAndReturnKey(params);
950 |
951 | return id.intValue();
952 | }
953 |
954 | @Override
955 | public Todo retrieveTodo(int id) {
956 |
957 | return jdbcTemplate.queryForObject(
958 | "SELECT * FROM TODO where id=?",
959 | new Object[] { id }, new TodoMapper());
960 |
961 | }
962 |
963 | @Override
964 | public void updateTodo(Todo todo) {
965 | jdbcTemplate
966 | .update("Update todo set user=?, desc=?, target_date=?, is_done=? where id=?",
967 | todo.getUser(), todo.getDesc(),
968 | new Timestamp(todo.getTargetDate()
969 | .getTime()),
970 | todo.isDone(), todo.getId());
971 |
972 | }
973 |
974 | @Override
975 | public void deleteTodo(int id) {
976 | jdbcTemplate.update("delete from todo where id=?",
977 | id);
978 | }
979 |
980 | }
981 | ```
982 | \src\main\java\com\example\demo\DemoApplication.java
983 | ```java
984 | package com.example.demo;
985 |
986 | import org.slf4j.Logger;
987 | import org.slf4j.LoggerFactory;
988 | import org.springframework.beans.factory.annotation.Autowired;
989 | import org.springframework.boot.CommandLineRunner;
990 | import org.springframework.boot.SpringApplication;
991 | import org.springframework.boot.autoconfigure.SpringBootApplication;
992 |
993 | import com.example.demo.data.student.GenericAllPurposeRepository;
994 | import com.example.demo.data.student.StudentRepository;
995 | import com.example.demo.data.todo.TodoDataService;
996 | import com.example.demo.entity.Passport;
997 | import com.example.demo.entity.Project;
998 | import com.example.demo.entity.Student;
999 | import com.example.demo.entity.Task;
1000 |
1001 | //In almost every relationship, independent of source and target sides, one of the two sides will have the join column in its table. That side is called the owning side or the owner of the relationship. The side that does not have the join column is called the non-owning or inverse side.
1002 | //Although we have described the owning side as being determined by the data schema, the object model must indicate the owning side through the use of the relationship mapping annotations. The absence of the mappedBy element in the mapping annotation implies ownership of the relationship, while the presence of the mappedBy element means the entity is on the inverse side of the relationship. The mappedBy element is described in subsequent sections.
1003 |
1004 | @SpringBootApplication
1005 | public class DemoApplication implements CommandLineRunner {
1006 |
1007 | private static final Logger log = LoggerFactory
1008 | .getLogger(DemoApplication.class);
1009 |
1010 | @Autowired
1011 | TodoDataService todoJPAService;
1012 |
1013 | @Autowired
1014 | StudentRepository studentRepository;
1015 |
1016 | @Autowired
1017 | GenericAllPurposeRepository genericRepository;
1018 |
1019 | public static void main(String[] args) {
1020 | SpringApplication.run(DemoApplication.class, args);
1021 | }
1022 |
1023 | @Override
1024 | public void run(String... strings) throws Exception {
1025 |
1026 | runAllStudentExamples();
1027 |
1028 | /*
1029 | * int todo1 = todoJPAService.addTodo("Ranga", "Dummy10", new Date(),
1030 | * false);
1031 | *
1032 | * int todo2 = todoJPAService.addTodo("Ranga", "Dummy11", new Date(),
1033 | * false);
1034 | *
1035 | * log.info( "Querying for todo records where user = 'Ranga':");
1036 | *
1037 | * todoJPAService.retrieveTodos("Ranga") .forEach(todo ->
1038 | * log.info(todo.toString()));
1039 | *
1040 | * todoJPAService.updateTodo(new Todo(todo1, "Ranga", "Dummy++", new
1041 | * Date(), false));
1042 | *
1043 | * log.info("Querying Todo by id " + todo1);
1044 | *
1045 | * log.info(todoJPAService.retrieveTodo(todo1) .toString());
1046 | *
1047 | * log.info("Deleting todo id " + todo2);
1048 | *
1049 | * todoJPAService.deleteTodo(todo2);
1050 | *
1051 | * log.info( "Querying for todo records where user = 'Ranga':");
1052 | *
1053 | * todoJPAService.retrieveTodos("Ranga") .forEach(todo ->
1054 | * log.info(todo.toString()));
1055 | *
1056 | */
1057 | }
1058 |
1059 | private void runAllStudentExamples() {
1060 | Passport passport = new Passport("L12344432",
1061 | "India");
1062 |
1063 | Student student = createStudent("dummy@dummy.com",
1064 | "Doe", passport);
1065 | student = genericRepository.createStudent(student);
1066 |
1067 | Project project = new Project();
1068 | project.setName("Project1");
1069 |
1070 | project = genericRepository.createProject(project);
1071 |
1072 | genericRepository.assignStudentToProject(
1073 | student.getId(), project.getId());
1074 |
1075 | Task task = new Task();
1076 | task.setName("Task1");
1077 | task.setProject(project);
1078 | task.setStudent(student);
1079 | genericRepository.createTask(task);
1080 |
1081 | Student student2 = studentRepository
1082 | .retrieveStudent(101);
1083 | System.out.println("student2 " + student2);
1084 |
1085 | printAllDataAfterTest();
1086 |
1087 | Passport passport2 = genericRepository
1088 | .getPassport(201);
1089 | System.out.println("passport 2 " + passport2);
1090 | System.out.println("passport 2 Student"
1091 | + passport2.getStudent());
1092 | }
1093 |
1094 | private Student createStudent(String email, String name,
1095 | Passport passport) {
1096 | Student student = new Student();
1097 | student.setEmail(email);
1098 | student.setName(name);
1099 | student.setPassportId(passport);
1100 | return student;
1101 | }
1102 |
1103 | public void printAllDataAfterTest() {
1104 | System.out.println(
1105 | studentRepository.retrieveAllStudents());
1106 | }
1107 | }
1108 | ```
1109 | \src\main\java\com\example\demo\entity\Address.java
1110 | ```java
1111 | package com.example.demo.entity;
1112 |
1113 | import javax.persistence.Embeddable;
1114 |
1115 | @Embeddable
1116 | public class Address {
1117 | private String street;
1118 | private String city;
1119 | private String state;
1120 | private String zip;
1121 | }
1122 | ```
1123 | \src\main\java\com\example\demo\entity\Employee.java
1124 | ```java
1125 | package com.example.demo.entity;
1126 |
1127 | import javax.persistence.DiscriminatorColumn;
1128 | import javax.persistence.Entity;
1129 | import javax.persistence.Id;
1130 | import javax.persistence.Inheritance;
1131 | import javax.persistence.InheritanceType;
1132 |
1133 | //@MappedSuperclass
1134 | @Entity
1135 | @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
1136 | @DiscriminatorColumn(name = "disc_type")
1137 | public abstract class Employee {
1138 | @Id
1139 | protected Integer employeeId;
1140 | }
1141 | ```
1142 | \src\main\java\com\example\demo\entity\FullTimeEmployee.java
1143 | ```java
1144 | package com.example.demo.entity;
1145 |
1146 | import javax.persistence.Entity;
1147 |
1148 | @Entity
1149 | public class FullTimeEmployee extends Employee {
1150 | protected Integer salary;
1151 | }
1152 | ```
1153 | \src\main\java\com\example\demo\entity\PartTimeEmployee.java
1154 | ```java
1155 | package com.example.demo.entity;
1156 |
1157 | import javax.persistence.Entity;
1158 |
1159 | @Entity
1160 | public class PartTimeEmployee extends Employee {
1161 | protected Float hourlyWage;
1162 | }
1163 | ```
1164 | \src\main\java\com\example\demo\entity\Passport.java
1165 | ```java
1166 | package com.example.demo.entity;
1167 |
1168 | import javax.persistence.Column;
1169 | import javax.persistence.Entity;
1170 | import javax.persistence.FetchType;
1171 | import javax.persistence.GeneratedValue;
1172 | import javax.persistence.GenerationType;
1173 | import javax.persistence.Id;
1174 | import javax.persistence.OneToOne;
1175 |
1176 | @Entity
1177 | public class Passport {
1178 |
1179 | @Id
1180 | @GeneratedValue(strategy = GenerationType.IDENTITY)
1181 | private long id;
1182 |
1183 | private String number;
1184 |
1185 | @Column(name = "issued_country")
1186 | private String issuedCountry;
1187 |
1188 | // Inverse Relationship
1189 | // bi-directional OneToOne relationship
1190 | // Column will not be created in the table
1191 | // Try removing mappedBy = "passport" => You will see that student_id column
1192 | // will be created in passport
1193 | @OneToOne(fetch = FetchType.LAZY, mappedBy = "passport")
1194 | private Student student;
1195 |
1196 | public Passport() {
1197 | super();
1198 | }
1199 |
1200 | public Passport(String number, String issuedCountry) {
1201 | super();
1202 | this.number = number;
1203 | this.issuedCountry = issuedCountry;
1204 | }
1205 |
1206 | public long getId() {
1207 | return id;
1208 | }
1209 |
1210 | public void setId(long id) {
1211 | this.id = id;
1212 | }
1213 |
1214 | public String getNumber() {
1215 | return number;
1216 | }
1217 |
1218 | public void setNumber(String number) {
1219 | this.number = number;
1220 | }
1221 |
1222 | public String getIssuedCountry() {
1223 | return issuedCountry;
1224 | }
1225 |
1226 | public void setIssuedCountry(String issuedCountry) {
1227 | this.issuedCountry = issuedCountry;
1228 | }
1229 |
1230 | public Student getStudent() {
1231 | return student;
1232 | }
1233 |
1234 | public void setStudent(Student student) {
1235 | this.student = student;
1236 | }
1237 |
1238 | @Override
1239 | public String toString() {
1240 | return "Passport [id=" + id + ", number=" + number
1241 | + ", issuedCountry=" + issuedCountry
1242 | + ", student=" + student + "]";
1243 | }
1244 |
1245 | }
1246 | ```
1247 | \src\main\java\com\example\demo\entity\Project.java
1248 | ```java
1249 | package com.example.demo.entity;
1250 |
1251 | import java.util.List;
1252 |
1253 | import javax.persistence.Entity;
1254 | import javax.persistence.GeneratedValue;
1255 | import javax.persistence.GenerationType;
1256 | import javax.persistence.Id;
1257 | import javax.persistence.ManyToMany;
1258 | import javax.persistence.OneToMany;
1259 |
1260 | @Entity
1261 | public class Project {
1262 |
1263 | @Id
1264 | @GeneratedValue(strategy = GenerationType.IDENTITY)
1265 | private long id;
1266 |
1267 | private String name;
1268 |
1269 | @OneToMany(mappedBy = "project")
1270 | private List tasks;
1271 |
1272 | // There are some important differences between this many-to-many
1273 | // relationship and the one-to-many relationship discussed earlier. The
1274 | // first is a mathematical inevitability: when a many-to-many relationship
1275 | // is bidirectional, both sides of the relationship are many-to-many
1276 | // mappings.
1277 | // The second difference is that there are no join columns on either side of
1278 | // the relationship. You will see in the next section that the only way to
1279 | // implement a many-to-many relationship is with a separate join table. The
1280 | // consequence of not having any join columns in either of the entity tables
1281 | // is that there is no way to determine which side is the owner of the
1282 | // relationship. Because every bidirectional relationship has to have both
1283 | // an owning side and an inverse side, we must pick one of the two entities
1284 | // to be the owner. In this example, we picked Employee to be owner of the
1285 | // relationship, but we could have just as easily picked Project instead. As
1286 | // in every other bidirectional relationship, the inverse side must use the
1287 | // mappedBy element to identify the owning attribute.
1288 | // Note that no matter which side is designated as the owner, the other side
1289 | // should include the mappedBy element; otherwise, the provider will think
1290 | // that both sides are the owner and that the mappings are separate
1291 | // unidirectional relationships.
1292 | @ManyToMany
1293 | // @JoinTable(name="STUDENT_PROJ",
1294 | // joinColumns=@JoinColumn(name="STUDENT_ID"),
1295 | // inverseJoinColumns=@JoinColumn(name="PROJECT_ID"))
1296 | private List students;
1297 |
1298 | public Project() {
1299 | super();
1300 | }
1301 |
1302 | public List getTasks() {
1303 | return tasks;
1304 | }
1305 |
1306 | public void setTasks(List tasks) {
1307 | this.tasks = tasks;
1308 | }
1309 |
1310 | public List getStudents() {
1311 | return students;
1312 | }
1313 |
1314 | public void setStudents(List students) {
1315 | this.students = students;
1316 | }
1317 |
1318 | public long getId() {
1319 | return id;
1320 | }
1321 |
1322 | public void setId(long id) {
1323 | this.id = id;
1324 | }
1325 |
1326 | public String getName() {
1327 | return name;
1328 | }
1329 |
1330 | public void setName(String name) {
1331 | this.name = name;
1332 | }
1333 |
1334 | @Override
1335 | public String toString() {
1336 | return "Project [id=" + id + ", name=" + name + "]";
1337 | }
1338 |
1339 | }
1340 | ```
1341 | \src\main\java\com\example\demo\entity\Student.java
1342 | ```java
1343 | package com.example.demo.entity;
1344 |
1345 | import java.util.List;
1346 |
1347 | import javax.persistence.CascadeType;
1348 | import javax.persistence.Embedded;
1349 | import javax.persistence.Entity;
1350 | import javax.persistence.GeneratedValue;
1351 | import javax.persistence.GenerationType;
1352 | import javax.persistence.Id;
1353 | import javax.persistence.ManyToMany;
1354 | import javax.persistence.NamedQuery;
1355 | import javax.persistence.OneToMany;
1356 | import javax.persistence.OneToOne;
1357 | import javax.persistence.Table;
1358 |
1359 | @Entity
1360 | @Table(name = "Student")
1361 | @NamedQuery(query = "select s from Student s", name = "find all students")
1362 | // SELECT p.number FROM Employee e JOIN e.phones p WHERE e.department.name =
1363 | // 'NA42' AND p.type = 'Cell'
1364 |
1365 | // Group ing
1366 | // SELECT d, COUNT(e), MAX(e.salary), AVG(e.salary)
1367 | // FROM Department d JOIN d.employees e
1368 | // GROUP BY d
1369 | // HAVING COUNT(e) >= 5
1370 |
1371 | // Query Params
1372 | // SELECT e
1373 | // FROM Employee e
1374 | // WHERE e.department = :dept AND
1375 | // e.salary > :base
1376 | // em.createQuery(QUERY, Long.class).setParameter("deptName",
1377 | // deptName).getSingleResult()
1378 |
1379 | // Read only queries ->
1380 | // @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
1381 |
1382 | // Criteria criteria = session.createCriteria(Book1.class)
1383 | // .add(Restrictions.eq("name", "Book 1"));
1384 | // List books=criteria.list();
1385 |
1386 | // Criterion nameRest = Restrictions.eq("name", "Hibernate
1387 | // Recipes").ignoreCase();
1388 | // gt (greater than), lt (less than), ge (greater than or equal to), isNull,
1389 | // isNotNull, isEmpty, isNotEmpty, between, in, le (less than or equal to)
1390 | // .add(Restrictions.like("name", "%Hibernate%"))
1391 | // .add(Restrictions.between("price", new Integer(100), new Integer(200)));
1392 | // .add(Restrictions.or(
1393 | // Restrictions.like("name", "%Hibernate%"),
1394 | // Restrictions.like("name", "%Java%")
1395 | // )
1396 | // )
1397 |
1398 | // Criteria criteria = session.createCriteria(Book.class)
1399 | // .add(Restrictions.like("name", "%Hibernate%"))
1400 | // .createCriteria("publisher")
1401 | // .add(Restrictions.eq("name", "Manning"));
1402 | // List books = criteria.list();
1403 | // .addOrder(Order.asc("name"))
1404 | // .addOrder(Order.desc("publishDate"));
1405 |
1406 | // .setProjection(Projections.projectionList()
1407 | // .add(Projections.groupProperty("publishDate"))
1408 | // .add(Projections.avg("price")));
1409 |
1410 | // @MappedSuperclass
1411 | // public class Auditable {
1412 | // @Getter
1413 | // @Setter
1414 | // @Temporal(TemporalType.TIMESTAMP)
1415 | // Date createDate;
1416 | // }
1417 |
1418 | // public class AuditableInterceptor extends EmptyInterceptor {
1419 | // @Override
1420 | // public boolean onSave(Object entity, Serializable id,
1421 | // Object[] state, String[] propertyNames,
1422 | // Type[] types) {
1423 | // if (entity instanceof Auditable) {
1424 | // for(int i=0;i tasks;
1468 |
1469 | @ManyToMany(mappedBy = "students")
1470 | private List projects;
1471 |
1472 | @Embedded
1473 | private Address address;
1474 |
1475 | // @ElementCollection
1476 | // @CollectionTable(name="EMP_PHONE")
1477 | // @MapKeyEnumerated(EnumType.STRING)
1478 | // @MapKeyColumn(name="PHONE_TYPE")
1479 | // @Column(name="PHONE_NUM")
1480 | // private Map phoneNumbers;
1481 | // public enum PhoneType { Home, Mobile, Work }
1482 |
1483 | public List getTasks() {
1484 | return tasks;
1485 | }
1486 |
1487 | public void setTasks(List tasks) {
1488 | this.tasks = tasks;
1489 | }
1490 |
1491 | public void setPassport(Passport passport) {
1492 | this.passport = passport;
1493 | }
1494 |
1495 | public long getId() {
1496 | return id;
1497 | }
1498 |
1499 | public void setId(long id) {
1500 | this.id = id;
1501 | }
1502 |
1503 | public String getName() {
1504 | return name;
1505 | }
1506 |
1507 | public void setName(String name) {
1508 | this.name = name;
1509 | }
1510 |
1511 | public Passport getPassport() {
1512 | return passport;
1513 | }
1514 |
1515 | public void setPassportId(Passport passport) {
1516 | this.passport = passport;
1517 | }
1518 |
1519 | public String getEmail() {
1520 | return email;
1521 | }
1522 |
1523 | public void setEmail(String email) {
1524 | this.email = email;
1525 | }
1526 |
1527 | @Override
1528 | public String toString() {
1529 | return "Student [id=" + id + ", name=" + name
1530 | + ", email=" + email + "]";
1531 | }
1532 |
1533 | }
1534 | ```
1535 | \src\main\java\com\example\demo\entity\Task.java
1536 | ```java
1537 | package com.example.demo.entity;
1538 |
1539 | import javax.persistence.Entity;
1540 | import javax.persistence.GeneratedValue;
1541 | import javax.persistence.GenerationType;
1542 | import javax.persistence.Id;
1543 | import javax.persistence.ManyToOne;
1544 |
1545 | @Entity
1546 | public class Task {
1547 |
1548 | public Task() {
1549 | super();
1550 | }
1551 |
1552 | @Id
1553 | @GeneratedValue(strategy = GenerationType.IDENTITY)
1554 | private long id;
1555 |
1556 | private String name;
1557 |
1558 | @ManyToOne
1559 | // @JoinColumn(name="PROJECT_ID")
1560 | private Project project;
1561 |
1562 | @ManyToOne
1563 | private Student student;
1564 |
1565 | public long getId() {
1566 | return id;
1567 | }
1568 |
1569 | public void setId(long id) {
1570 | this.id = id;
1571 | }
1572 |
1573 | public Project getProject() {
1574 | return project;
1575 | }
1576 |
1577 | public void setProject(Project project) {
1578 | this.project = project;
1579 | }
1580 |
1581 | public Student getStudent() {
1582 | return student;
1583 | }
1584 |
1585 | public void setStudent(Student student) {
1586 | this.student = student;
1587 | }
1588 |
1589 | public String getName() {
1590 | return name;
1591 | }
1592 |
1593 | public void setName(String name) {
1594 | this.name = name;
1595 | }
1596 |
1597 | @Override
1598 | public String toString() {
1599 | return "Task [id=" + id + ", name=" + name + "]";
1600 | }
1601 | }
1602 | ```
1603 | \src\main\java\com\example\demo\entity\Todo.java
1604 | ```java
1605 | package com.example.demo.entity;
1606 |
1607 | import java.util.Date;
1608 |
1609 | import javax.persistence.Entity;
1610 | import javax.persistence.GeneratedValue;
1611 | import javax.persistence.GenerationType;
1612 | import javax.persistence.Id;
1613 | import javax.persistence.NamedQuery;
1614 | import javax.persistence.Table;
1615 |
1616 | @Entity
1617 | @Table(name = "Todo")
1618 | @NamedQuery(query = "select t from Todo t where user=?", name = "find all todos for user")
1619 | public class Todo {
1620 |
1621 | @Id
1622 | @GeneratedValue(strategy = GenerationType.IDENTITY)
1623 | private int id;
1624 |
1625 | private String user;
1626 |
1627 | private String desc;
1628 |
1629 | private Date targetDate;
1630 |
1631 | private boolean isDone;
1632 |
1633 | public Todo() {
1634 | super();
1635 | }
1636 |
1637 | public Todo(int id, String user, String desc,
1638 | Date targetDate, boolean isDone) {
1639 | super();
1640 | this.id = id;
1641 | this.user = user;
1642 | this.desc = desc;
1643 | this.targetDate = targetDate;
1644 | this.isDone = isDone;
1645 | }
1646 |
1647 | public Todo(String user, String desc, Date targetDate,
1648 | boolean isDone) {
1649 | super();
1650 | this.user = user;
1651 | this.desc = desc;
1652 | this.targetDate = targetDate;
1653 | this.isDone = isDone;
1654 | }
1655 |
1656 | public int getId() {
1657 | return id;
1658 | }
1659 |
1660 | public void setId(int id) {
1661 | this.id = id;
1662 | }
1663 |
1664 | public String getUser() {
1665 | return user;
1666 | }
1667 |
1668 | public void setUser(String user) {
1669 | this.user = user;
1670 | }
1671 |
1672 | public String getDesc() {
1673 | return desc;
1674 | }
1675 |
1676 | public void setDesc(String desc) {
1677 | this.desc = desc;
1678 | }
1679 |
1680 | public Date getTargetDate() {
1681 | return targetDate;
1682 | }
1683 |
1684 | public void setTargetDate(Date targetDate) {
1685 | this.targetDate = targetDate;
1686 | }
1687 |
1688 | public boolean isDone() {
1689 | return isDone;
1690 | }
1691 |
1692 | public void setDone(boolean isDone) {
1693 | this.isDone = isDone;
1694 | }
1695 |
1696 | @Override
1697 | public int hashCode() {
1698 | final int prime = 31;
1699 | int result = 1;
1700 | result = prime * result + id;
1701 | return result;
1702 | }
1703 |
1704 | @Override
1705 | public boolean equals(Object obj) {
1706 | if (this == obj)
1707 | return true;
1708 | if (obj == null)
1709 | return false;
1710 | if (getClass() != obj.getClass())
1711 | return false;
1712 | Todo other = (Todo) obj;
1713 | if (id != other.id)
1714 | return false;
1715 | return true;
1716 | }
1717 |
1718 | @Override
1719 | public String toString() {
1720 | return String.format(
1721 | "Todo [id=%s, user=%s, desc=%s, targetDate=%s, isDone=%s]",
1722 | id, user, desc, targetDate, isDone);
1723 | }
1724 |
1725 | }
1726 | ```
1727 | \src\main\java\com\example\demo\rest\TodoRestService.java
1728 | ```java
1729 | package com.example.demo.rest;
1730 |
1731 | import java.net.URI;
1732 | import java.sql.SQLException;
1733 | import java.util.List;
1734 |
1735 | import org.springframework.beans.factory.annotation.Autowired;
1736 | import org.springframework.http.ResponseEntity;
1737 | import org.springframework.web.bind.annotation.DeleteMapping;
1738 | import org.springframework.web.bind.annotation.GetMapping;
1739 | import org.springframework.web.bind.annotation.PathVariable;
1740 | import org.springframework.web.bind.annotation.PostMapping;
1741 | import org.springframework.web.bind.annotation.PutMapping;
1742 | import org.springframework.web.bind.annotation.RequestBody;
1743 | import org.springframework.web.bind.annotation.RestController;
1744 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
1745 |
1746 | import com.example.demo.data.todo.TodoJPAService;
1747 | import com.example.demo.entity.Todo;
1748 |
1749 | @RestController
1750 | public class TodoRestService {
1751 |
1752 | @Autowired
1753 | TodoJPAService todoJPAService;
1754 |
1755 | @GetMapping("/todos/user/{user}")
1756 | public List retrieveTodos(
1757 | @PathVariable String user) throws SQLException {
1758 | return todoJPAService.retrieveTodos(user);
1759 | }
1760 |
1761 | @PostMapping("/todos")
1762 | public ResponseEntity addTodo(
1763 | @RequestBody Todo todo) throws SQLException {
1764 | int todoID = todoJPAService.addTodo(todo.getUser(),
1765 | todo.getDesc(), todo.getTargetDate(),
1766 | todo.isDone());
1767 |
1768 | URI location = ServletUriComponentsBuilder
1769 | .fromCurrentRequest().path("/{id}")
1770 | .buildAndExpand(todoID).toUri();
1771 |
1772 | return ResponseEntity.created(location).build();
1773 | }
1774 |
1775 | @GetMapping("/todos/{id}")
1776 | public Todo retrieveTodo(@PathVariable int id)
1777 | throws SQLException {
1778 | return todoJPAService.retrieveTodo(id);
1779 | }
1780 |
1781 | @PutMapping("/todos")
1782 | public void updateTodo(@RequestBody Todo todo)
1783 | throws SQLException {
1784 | todoJPAService.updateTodo(todo);
1785 | }
1786 |
1787 | @DeleteMapping("/todos/{id}")
1788 | public void deleteTodo(@PathVariable int id)
1789 | throws SQLException {
1790 | todoJPAService.deleteTodo(id);
1791 | }
1792 | }
1793 | ```
1794 | \src\main\resources\application.properties
1795 | ```properties
1796 | #logging.level.: DEBUG
1797 | spring.h2.console.enabled: true
1798 |
1799 | # Log everything. Good for troubleshooting
1800 | #logging.level.org.hibernate=debug
1801 | #logging.level.org.springframework=debug
1802 | #logging.level.javax.servlet=info
1803 |
1804 | # Log all JDBC parameters
1805 | #logging.level.org.hibernate.type=all
1806 | ```
1807 | \src\main\resources\data.sql
1808 | ```sql
1809 | INSERT INTO passport(id,number,issued_country)
1810 | VALUES (201,'L1234567','India');
1811 | INSERT INTO passport(id,number,issued_country)
1812 | VALUES (202,'L1234568','India');
1813 |
1814 |
1815 | INSERT INTO student(id, name, passport_id, email )
1816 | VALUES (101,'Jane', 201, 'jane@doe.com');
1817 | INSERT INTO student(id, name, passport_id, email )
1818 | VALUES (102,'Doe', 202, 'doe@doe.com');
1819 | ```
1820 | \src\main\resources\schema-old.sql
1821 | ```
1822 | DROP TABLE todo IF EXISTS;
1823 | /* NOT NEEDED WHEN JPA IS ACTIVE
1824 | CREATE TABLE todo(
1825 | id SERIAL auto_increment primary key,
1826 | user VARCHAR(255),
1827 | desc VARCHAR(255),
1828 | target_date TIMESTAMP,
1829 | is_done BOOLEAN);
1830 | */
1831 | ```
1832 | \src\test\java\com\example\demo\DemoApplicationTests.java
1833 | ```java
1834 | package com.example.demo;
1835 |
1836 | import org.junit.Test;
1837 | import org.junit.runner.RunWith;
1838 | import org.springframework.boot.test.context.SpringBootTest;
1839 | import org.springframework.test.context.junit4.SpringRunner;
1840 |
1841 | @RunWith(SpringRunner.class)
1842 | @SpringBootTest
1843 | public class DemoApplicationTests {
1844 |
1845 | @Test
1846 | public void contextLoads() {
1847 | }
1848 |
1849 | }
1850 | ```
1851 |
--------------------------------------------------------------------------------