View Javadoc
1   package net.sumaris.core.dao.technical.jpa;
2   
3   /*-
4    * #%L
5    * SUMARiS:: Core shared
6    * %%
7    * Copyright (C) 2018 - 2019 SUMARiS Consortium
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.querydsl.jpa.impl.JPAQuery;
26  import net.sumaris.core.config.SumarisConfiguration;
27  import net.sumaris.core.dao.technical.Daos;
28  import net.sumaris.core.dao.technical.SortDirection;
29  import net.sumaris.core.dao.technical.model.IEntity;
30  import net.sumaris.core.exception.SumarisTechnicalException;
31  import org.hibernate.LockOptions;
32  import org.hibernate.Session;
33  import org.hibernate.dialect.Dialect;
34  import org.springframework.beans.factory.annotation.Autowired;
35  import org.springframework.dao.DataAccessResourceFailureException;
36  import org.springframework.dao.DataIntegrityViolationException;
37  import org.springframework.data.domain.PageRequest;
38  import org.springframework.data.domain.Pageable;
39  import org.springframework.data.domain.Sort;
40  import org.springframework.data.jpa.domain.Specification;
41  import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
42  import org.springframework.data.repository.NoRepositoryBean;
43  
44  import javax.persistence.EntityManager;
45  import javax.persistence.LockModeType;
46  import javax.sql.DataSource;
47  import java.io.Serializable;
48  import java.sql.SQLException;
49  import java.sql.Timestamp;
50  import java.util.Arrays;
51  
52  /**
53   * @author Benoit Lavenier <benoit.lavenier@e-is.pro>*
54   */
55  public class SumarisJpaRepositoryImpl<T, ID extends Serializable>
56          extends SimpleJpaRepository<T, ID>
57          implements SumarisJpaRepository<T, ID> {
58  
59      private boolean debugEntityLoad = false;
60  
61      private EntityManager entityManager;
62  
63      @Autowired
64      private DataSource dataSource;
65  
66      // There are two constructors to choose from, either can be used.
67      public SumarisJpaRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
68          super(domainClass, entityManager);
69  
70          // This is the recommended method for accessing inherited class dependencies.
71          this.entityManager = entityManager;
72  
73      }
74  
75      @Override
76      public T createEntity() {
77          try {
78              return getDomainClass().newInstance();
79          } catch (Exception e) {
80              throw new RuntimeException(e);
81          }
82      }
83  
84      @SuppressWarnings("unchecked")
85      @Override
86      public <C extends Serializable> C load(Class<C> clazz, Serializable id) {
87  
88          if (debugEntityLoad) {
89              C load = entityManager.find(clazz, id);
90              if (load == null) {
91                  throw new DataIntegrityViolationException("Unable to load entity " + clazz.getName() + " with identifier '" + id + "': not found in database.");
92              }
93          }
94          return entityManager.unwrap(Session.class).load(clazz, id);
95      }
96  
97      /**
98       * <p>get.</p>
99       *
100      * @param clazz a {@link Class} object.
101      * @param id a {@link Serializable} object.
102      * @param <T> a T object.
103      * @return a T object.
104      */
105     @SuppressWarnings("unchecked")
106     public <C extends Serializable> C get(Class<? extends C> clazz, Serializable id) {
107         return this.entityManager.find(clazz, id);
108     }
109 
110     /**
111      * <p>get.</p>
112      *
113      * @param clazz a {@link Class} object.
114      * @param id a {@link Serializable} object.
115      * @param lockOptions a {@link LockOptions} object.
116      * @param <T> a T object.
117      * @return a T object.
118      */
119     @SuppressWarnings("unchecked")
120     public <C extends Serializable> C get(Class<? extends C> clazz, Serializable id, LockModeType lockModeType) {
121         C entity = entityManager.find(clazz, id);
122         entityManager.lock(entity, lockModeType);
123         return entity;
124     }
125 
126     /* -- protected method -- */
127 
128     protected EntityManager getEntityManager() {
129         return entityManager;
130     }
131 
132     protected Timestamp getDatabaseCurrentTimestamp() {
133 
134         if (dataSource == null) return new Timestamp(System.currentTimeMillis());
135 
136         try {
137             final Dialect dialect = Dialect.getDialect(SumarisConfiguration.getInstance().getConnectionProperties());
138             final String sql = dialect.getCurrentTimestampSelectString();
139             Object r = Daos.sqlUnique(dataSource, sql);
140             return Daos.toTimestampFromJdbcResult(r);
141         } catch (DataAccessResourceFailureException | SQLException e) {
142             throw new SumarisTechnicalException(e);
143         }
144     }
145 
146     protected <T> JPAQuery<T> createQuery() {
147         return new JPAQuery<>(entityManager);
148     }
149 
150     protected <T extends IEntity<?>> Specification<T> and(Specification<T>... specs) {
151         Specification<T> result = null;
152         for (Specification<T> item: specs) {
153             if (item != null) {
154                 if (result == null) {
155                     result = Specification.where(item);
156                 }
157                 else {
158                     result.and(item);
159                 }
160             }
161         }
162         return result;
163     }
164 
165     protected Pageable getPageable(int offset, int size, String sortAttribute, SortDirection sortDirection) {
166         if (sortAttribute != null) {
167             return PageRequest.of(offset / size, size,
168                     (sortDirection == null) ? Sort.Direction.ASC :
169                             Sort.Direction.fromString(sortDirection.toString()),
170                     sortAttribute);
171         }
172         return PageRequest.of(offset / size, size);
173     }
174 }