import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
-import javax.persistence.NamedNativeQueries;
-import javax.persistence.NamedNativeQuery;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
+//import javax.persistence.NamedNativeQueries;
+//import javax.persistence.NamedNativeQuery;
+//import javax.persistence.NamedQueries;
+//import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.Max;
// So you'd better use @Query.
//http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query
//See: de.spring.persistence.example.repository.AdRepository
-@NamedQueries(
- {
- @NamedQuery(
- name="Ad.findByIdQuery",
- query="select a FROM AD a WHERE a.id = :id")
- }
-
-)
+//@NamedQueries(
+// {
+// @NamedQuery(
+// name="Ad.findByIdQuery",
+// query="select a from Ad a where a.id = :id)
+// }
+//
+//)
// 1. Native query IS NOT JPL. It is not portable and it is written directly in the native language
// of the store. We can use special features at the cost of portability.
// 2. Instead of annotating the domain class we should be using @Query annotation at the query method
// So you'd better use @Query.
// http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query
// See: de.spring.persistence.example.repository.AdRepository
-@NamedNativeQueries(
- {
- @NamedNativeQuery(
- name="Ad.findByIdNativeQuery",
- query="SELECT * FROM AD WHERE AD.ID = :id",
- resultClass=Ad.class)
- }
-)
+//@NamedNativeQueries(
+// {
+// @NamedNativeQuery(
+// name="Ad.findByIdNativeQuery",
+// query="SELECT * FROM ad WHERE ad.id = :id",
+// resultClass=Ad.class)
+// }
+//)
public class Ad implements Serializable {
@Id
package de.spring.persistence.example.repository;
import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import de.spring.persistence.example.domain.Ad;
public interface AdDescriptionRepository extends PagingAndSortingRepository<AdDescription, Long> {
// Custom Query method
- Page<AdDescription> findByAd(Ad ad);
+ Page<AdDescription> findByAd(Ad ad, Pageable pageable);
}
// Named Native Query (using the native language of the store) It is not portable.
// See de.spring.persistence.example.domain.Ad
- @Query(value="SELECT * FROM AD WHERE AD.ID = :id", nativeQuery=true)
+ @Query(value="SELECT * FROM ad WHERE ad.id = :id", nativeQuery=true)
Ad findByIdNativeQuery(@Param("id") Long id);
// Named Query (using JPL) It is portable.
// See de.spring.persistence.example.domain.Ad
- @Query("SELECT * FROM AD WHERE AD.ID = :id")
+ @Query("select a from Ad a where a.id = :id")
Ad findByIdQuery(@Param("id") Long id);
}
--- /dev/null
+package org.resthub.common.service;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * CRUD Service interface.
+ *
+ * @param <T> Your resource POJO to manage, maybe an entity or DTO class
+ * @param <ID> Resource id type, usually Long or String
+ */
+public interface CrudService<T, ID extends Serializable> {
+
+ /**
+ * Create new resource.
+ *
+ * @param resource Resource to create
+ * @return new resource
+ */
+ T create(T resource);
+
+ /**
+ * Update existing resource.
+ *
+ * @param resource Resource to update
+ * @return resource updated
+ */
+ T update(T resource);
+
+ /**
+ * Delete existing resource.
+ *
+ * @param resource Resource to delete
+ */
+ void delete(T resource);
+
+ /**
+ * Delete existing resource.
+ *
+ * @param id Resource id
+ */
+ void delete(ID id);
+
+ /**
+ * Delete all existing resource. Do not use cascade remove (not a choice -> JPA specs)
+ */
+ void deleteAll();
+
+ /**
+ * Delete all existing resource, including linked entities with cascade delete
+ */
+ void deleteAllWithCascade();
+
+ /**
+ * Find resource by id.
+ *
+ * @param id Resource id
+ * @return resource
+ */
+ T findById(ID id);
+
+ /**
+ * Find resources by their ids.
+ *
+ * @param ids Resource ids
+ * @return a list of retrieved resources, empty if no resource found
+ */
+ Iterable<T> findByIds(Set<ID> ids);
+
+ /**
+ * Find all resources.
+ *
+ * @return a list of all resources.
+ */
+ Iterable<T> findAll();
+
+ /**
+ * Find all resources (pageable).
+ *
+ * @param pageRequest page request
+ * @return resources
+ */
+ Page<T> findAll(Pageable pageRequest);
+
+ /**
+ * Count all resources.
+ *
+ * @return number of resources
+ */
+ Long count();
+}
--- /dev/null
+package org.resthub.web.controller;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import org.resthub.common.exception.NotFoundException;
+import org.resthub.common.service.CrudService;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * Abstract REST controller using a service implementation
+ * <p/>
+ * <p>You should extend this class when you want to use a 3 layers pattern : Repository, Service and Controller
+ * If you don't have a real service (also called business layer), consider using RepositoryBasedRestController</p>
+ * <p/>
+ * <p>Default implementation uses "id" field (usually a Long) in order to identify resources in web request.
+ * If your want to identity resources by a slug (human readable identifier), your should override findById() method with for example :
+ * <p/>
+ * <pre>
+ * <code>
+ * {@literal @}Override
+ * public Sample findById({@literal @}PathVariable String id) {
+ * Sample sample = this.service.findByName(id);
+ * if (sample == null) {
+ * throw new NotFoundException();
+ * }
+ * return sample;
+ * }
+ * </code>
+ * </pre>
+ *
+ * @param <T> Your resource class to manage, maybe an entity or DTO class
+ * @param <ID> Resource id type, usually Long or String
+ * @param <S> The service class
+ * @see RepositoryBasedRestController
+ */
+public abstract class ServiceBasedRestController<T, ID extends Serializable, S extends CrudService> implements
+ RestController<T, ID> {
+
+ protected S service;
+
+ /**
+ * You should override this setter in order to inject your service with @Inject annotation
+ *
+ * @param service The service to be injected
+ */
+ public void setService(S service) {
+ this.service = service;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public T create(@RequestBody T resource) {
+ return (T) this.service.create(resource);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public T update(@PathVariable ID id, @RequestBody T resource) {
+ Assert.notNull(id, "id cannot be null");
+
+ T retreivedResource = this.findById(id);
+ if (retreivedResource == null) {
+ throw new NotFoundException();
+ }
+
+ return (T) this.service.update(resource);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Iterable<T> findAll() {
+ return service.findAll();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Page<T> findPaginated(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
+ @RequestParam(value = "size", required = false, defaultValue = "10") Integer size,
+ @RequestParam(value = "direction", required = false, defaultValue = "") String direction,
+ @RequestParam(value = "properties", required = false) String properties) {
+ Assert.isTrue(page > 0, "Page index must be greater than 0");
+ Assert.isTrue(direction.isEmpty() || direction.equalsIgnoreCase(Sort.Direction.ASC.toString()) || direction.equalsIgnoreCase(Sort.Direction.DESC.toString()), "Direction should be ASC or DESC");
+ if (direction.isEmpty()) {
+ return this.service.findAll(new PageRequest(page - 1, size));
+ } else {
+ Assert.notNull(properties);
+ return this.service.findAll(new PageRequest(page - 1, size, new Sort(Sort.Direction.fromString(direction.toUpperCase()), properties.split(","))));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public T findById(@PathVariable ID id) {
+ T resource = (T) this.service.findById(id);
+ if (resource == null) {
+ throw new NotFoundException();
+ }
+
+ return resource;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Iterable<T> findByIds(@RequestParam(value = "ids[]") Set<ID> ids) {
+ Assert.notNull(ids, "ids list cannot be null");
+ return this.service.findByIds(ids);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void delete() {
+ this.service.deleteAllWithCascade();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void delete(@PathVariable ID id) {
+ T resource = this.findById(id);
+ this.service.delete(resource);
+ }
+}
+