77import java .sql .PreparedStatement ;
88import java .sql .ResultSet ;
99import java .sql .SQLException ;
10+ import java .util .AbstractMap ;
1011import java .util .ArrayList ;
1112import java .util .Collections ;
1213import java .util .HashSet ;
1314import java .util .List ;
15+ import java .util .Map ;
1416import java .util .Set ;
1517import java .util .stream .Collectors ;
1618import java .util .stream .Stream ;
1719
20+ import javax .persistence .EntityManager ;
21+ import javax .persistence .Query ;
22+ import javax .persistence .TypedQuery ;
23+ import javax .persistence .criteria .CriteriaBuilder ;
24+ import javax .persistence .criteria .CriteriaQuery ;
25+ import javax .persistence .criteria .Order ;
26+ import javax .persistence .criteria .Root ;
27+ import javax .persistence .metamodel .SingularAttribute ;
1828import javax .sql .DataSource ;
1929
2030import org .springframework .stereotype .Component ;
2737public class AccountDAO {
2838
2939 private final DataSource dataSource ;
40+ private final EntityManager em ;
3041
31- public AccountDAO (DataSource dataSource ) {
42+ public AccountDAO (DataSource dataSource , EntityManager em ) {
3243 this .dataSource = dataSource ;
44+ this .em = em ;
3345 }
3446
3547 /**
@@ -63,6 +75,26 @@ public List<AccountDTO> unsafeFindAccountsByCustomerId(String customerId) {
6375 }
6476 }
6577
78+ /**
79+ * Return all accounts owned by a given customer,given his/her external id - JPA version
80+ *
81+ * @param customerId
82+ * @return
83+ */
84+ public List <AccountDTO > unsafeJpaFindAccountsByCustomerId (String customerId ) {
85+ String jql = "from Account where customerId = '" + customerId + "'" ;
86+ TypedQuery <Account > q = em .createQuery (jql , Account .class );
87+ return q .getResultList ()
88+ .stream ()
89+ .map (a -> AccountDTO .builder ()
90+ .accNumber (a .getAccNumber ())
91+ .balance (a .getBalance ())
92+ .branchId (a .getAccNumber ())
93+ .customerId (a .getCustomerId ())
94+ .build ())
95+ .collect (Collectors .toList ());
96+ }
97+
6698 /**
6799 * Return all accounts owned by a given customer,given his/her external id
68100 *
@@ -71,7 +103,7 @@ public List<AccountDTO> unsafeFindAccountsByCustomerId(String customerId) {
71103 */
72104 public List <AccountDTO > safeFindAccountsByCustomerId (String customerId ) {
73105
74- String sql = "select " + " customer_id,acc_number, branch_id,balance from Accounts where customer_id = ?" ;
106+ String sql = "select customer_id, branch_id,acc_number ,balance from Accounts where customer_id = ?" ;
75107
76108 try (Connection c = dataSource .getConnection (); PreparedStatement p = c .prepareStatement (sql )) {
77109 p .setString (1 , customerId );
@@ -93,23 +125,73 @@ public List<AccountDTO> safeFindAccountsByCustomerId(String customerId) {
93125 }
94126 }
95127
128+ /**
129+ * Return all accounts owned by a given customer,given his/her external id - JPA version
130+ *
131+ * @param customerId
132+ * @return
133+ */
134+ public List <AccountDTO > safeJpaFindAccountsByCustomerId (String customerId ) {
135+
136+ String jql = "from Account where customerId = :customerId" ;
137+ TypedQuery <Account > q = em .createQuery (jql , Account .class )
138+ .setParameter ("customerId" , customerId );
139+
140+ return q .getResultList ()
141+ .stream ()
142+ .map (a -> AccountDTO .builder ()
143+ .accNumber (a .getAccNumber ())
144+ .balance (a .getBalance ())
145+ .branchId (a .getAccNumber ())
146+ .customerId (a .getCustomerId ())
147+ .build ())
148+ .collect (Collectors .toList ());
149+ }
150+
151+ /**
152+ * Return all accounts owned by a given customer,given his/her external id - JPA version
153+ *
154+ * @param customerId
155+ * @return
156+ */
157+ public List <AccountDTO > safeJpaCriteriaFindAccountsByCustomerId (String customerId ) {
158+
159+ CriteriaBuilder cb = em .getCriteriaBuilder ();
160+ CriteriaQuery <Account > cq = cb .createQuery (Account .class );
161+ Root <Account > root = cq .from (Account .class );
162+ cq .select (root )
163+ .where (cb .equal (root .get (Account_ .customerId ), customerId ));
164+
165+ TypedQuery <Account > q = em .createQuery (cq );
166+
167+ return q .getResultList ()
168+ .stream ()
169+ .map (a -> AccountDTO .builder ()
170+ .accNumber (a .getAccNumber ())
171+ .balance (a .getBalance ())
172+ .branchId (a .getAccNumber ())
173+ .customerId (a .getCustomerId ())
174+ .build ())
175+ .collect (Collectors .toList ());
176+ }
177+
96178 private static final Set <String > VALID_COLUMNS_FOR_ORDER_BY = Stream .of ("acc_number" , "branch_id" , "balance" )
97179 .collect (Collectors .toCollection (HashSet ::new ));
98180
181+
99182 /**
100183 * Return all accounts owned by a given customer,given his/her external id
101184 *
102185 * @param customerId
103186 * @return
104187 */
105- public List <AccountDTO > safeFindAccountsByCustomerId (String customerId , String orderBy ) {
188+ public List <AccountDTO > safeFindAccountsByCustomerId (String customerId , String orderBy ) {
106189
107190 String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ? " ;
108191
109192 if (VALID_COLUMNS_FOR_ORDER_BY .contains (orderBy )) {
110193 sql = sql + " order by " + orderBy ;
111- }
112- else {
194+ } else {
113195 throw new IllegalArgumentException ("Nice try!" );
114196 }
115197
@@ -135,35 +217,82 @@ public List<AccountDTO> safeFindAccountsByCustomerId(String customerId, String o
135217 }
136218 }
137219
220+
221+ private static final Map <String ,SingularAttribute <Account ,?>> VALID_JPA_COLUMNS_FOR_ORDER_BY = Stream .of (
222+ new AbstractMap .SimpleEntry <>(Account_ .ACC_NUMBER , Account_ .accNumber ),
223+ new AbstractMap .SimpleEntry <>(Account_ .BRANCH_ID , Account_ .branchId ),
224+ new AbstractMap .SimpleEntry <>(Account_ .BALANCE , Account_ .balance )
225+ )
226+ .collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
227+
228+ /**
229+ * Return all accounts owned by a given customer,given his/her external id
230+ *
231+ * @param customerId
232+ * @return
233+ */
234+ public List <AccountDTO > safeJpaFindAccountsByCustomerId (String customerId , String orderBy ) {
235+
236+ SingularAttribute <Account ,?> orderByAttribute = VALID_JPA_COLUMNS_FOR_ORDER_BY .get (orderBy );
237+ if ( orderByAttribute == null ) {
238+ throw new IllegalArgumentException ("Nice try!" );
239+ }
240+
241+ CriteriaBuilder cb = em .getCriteriaBuilder ();
242+ CriteriaQuery <Account > cq = cb .createQuery (Account .class );
243+ Root <Account > root = cq .from (Account .class );
244+ cq .select (root )
245+ .where (cb .equal (root .get (Account_ .customerId ), customerId ))
246+ .orderBy (cb .asc (root .get (orderByAttribute )));
247+
248+ TypedQuery <Account > q = em .createQuery (cq );
249+
250+ return q .getResultList ()
251+ .stream ()
252+ .map (a -> AccountDTO .builder ()
253+ .accNumber (a .getAccNumber ())
254+ .balance (a .getBalance ())
255+ .branchId (a .getAccNumber ())
256+ .customerId (a .getCustomerId ())
257+ .build ())
258+ .collect (Collectors .toList ());
259+
260+ }
261+
138262 /**
139263 * Invalid placeholder usage example
140264 *
141265 * @param tableName
142266 * @return
143267 */
144- public List <AccountDTO > wrongCountRecordsByTableName (String tableName ) {
268+ public Long wrongCountRecordsByTableName (String tableName ) {
269+
270+ try (Connection c = dataSource .getConnection (); PreparedStatement p = c .prepareStatement ("select count(*) from ?" )) {
145271
146- try (Connection c = dataSource .getConnection ();
147- PreparedStatement p = c .prepareStatement ("select count(*) from ?" )) {
148-
149272 p .setString (1 , tableName );
150273 ResultSet rs = p .executeQuery ();
151- List <AccountDTO > accounts = new ArrayList <>();
152- while (rs .next ()) {
153- AccountDTO acc = AccountDTO .builder ()
154- .customerId (rs .getString ("customerId" ))
155- .branchId (rs .getString ("branch_id" ))
156- .accNumber (rs .getString ("acc_number" ))
157- .balance (rs .getBigDecimal ("balance" ))
158- .build ();
159-
160- accounts .add (acc );
161- }
274+ rs .next ();
275+ return rs .getLong (1 );
162276
163- return accounts ;
164277 } catch (SQLException ex ) {
165278 throw new RuntimeException (ex );
166279 }
167280 }
168281
282+ /**
283+ * Invalid placeholder usage example - JPA
284+ *
285+ * @param tableName
286+ * @return
287+ */
288+ public Long wrongJpaCountRecordsByTableName (String tableName ) {
289+
290+ String jql = "select count(*) from :tableName" ;
291+ TypedQuery <Long > q = em .createQuery (jql , Long .class )
292+ .setParameter ("tableName" , tableName );
293+
294+ return q .getSingleResult ();
295+
296+ }
297+
169298}
0 commit comments