Wednesday, March 29, 2017

Spring Data



Cache

Redis
http://www.cnblogs.com/moonandstar08/p/5149585.html

http://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra-template.id-handling
  @PrimaryKey("user_id")
  private String userId;

org.springframework.data.cassandra.repository.support.SimpleCassandraRepository.delete(T)
public void delete(T entity) {
  delete(entityInformation.getId(entity));
}
  @PrimaryKeyColumn(name = "person_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
  private String personId;

  @PrimaryKeyColumn(name = "event_code", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
  private int eventCode;

  @PrimaryKeyColumn(name = "event_time", ordinal = 2, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
  private Date eventTime;


A primary key class is a composite primary key class that is mapped to multiple fields or properties of the entity. It’s annotated with @PrimaryKeyClass and defines equals and hashCode methods. The semantics of value equality for these methods should be consistent with the database equality for the database types to which the key is mapped. Primary key classes can be used with Repositories (as the Id type) and to represent an entities' identity in a single complex object.
@PrimaryKeyClass
public class LoginEventKey implements Serializable {

  @PrimaryKeyColumn(name = "person_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
  private String personId;

  @PrimaryKeyColumn(name = "event_code", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
  private int eventCode;

  @PrimaryKeyColumn(name = "event_time", ordinal = 2, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
  private Date eventTime;

  // other methods omitted for brevity
}
  @PrimaryKey
  private LoginEventKey key;

http://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra.custom-converters
static class PersonWriteConverter implements Converter<Person, String> {

  public String convert(Person source) {

    try {
      return new ObjectMapper().writeValueAsString(source);
    } catch (IOException e) {
      throw new IllegalStateException(e);
    }
  }
}

@Configuration
public static class Config extends AbstractCassandraConfiguration {

  @Override
  public CustomConversions customConversions() {

    List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
    converters.add(new PersonReadConverter());
    converters.add(new PersonWriteConverter());

    return new CustomConversions(converters);
  }

  // other methods omitted...
}
http://javabeat.net/introduction-to-spring-converters-and-formatters/
28 GenericConversionService conversionService = new GenericConversionService();
29
30 Converter<Article, String> customConverter = new ArticleToStringConverter();
31conversionService.addConverter(customConverter);
32
33 Article article = new Article("Introduction to Spring Converters", "Core Spring");
34String result = conversionService.convert(article, String.class);
35        

http://ankushs92.github.io/tutorial/2016/05/03/pagination-with-spring-boot.html
@Converter
public class ListToStringConveter implements AttributeConverter<List<String>, String> {

    @Override
    public String convertToDatabaseColumn(List<String> attribute) {
        if (attribute == null || attribute.isEmpty()) {
            return "";
        }
        return StringUtils.join(attribute, ",");
    }

    @Override
    public List<String> convertToEntityAttribute(String dbData) {
        if (dbData == null || dbData.trim().length() == 0) {
            return new ArrayList<String>();
        }

        String[] data = dbData.split(",");
        return Arrays.asList(data);
    }
}
You can use the autoApply attribute of the Converter to apply the converter to any supported type.
@Converter(autoApply=true)
public class ListToStringConveter implements AttributeConverter<List<String>, String> {...}
It is dangerous in a real world project when there are some List you do not want to be converted.
Alternatively, you can apply it on the property via a @Convert annotation.
@Column(name="TAGS")
@Convert(converter = ListToStringConveter.class)
private List<String> tags=new ArrayList<>();
You can also place it on class.
@Converts(value={
    @Convert(attributeName="tags", converter = ListToStringConveter.class)
})
public class Post implements Serializable {...}


  • @Embeddable key of a OneToMany Map type property.
  • @Embeded property
  • @ElementCollection property

  • When using the specification pattern we move business rules into extra classes called specifications.
    em.createQuery(
        "from User where username = :username", User.class
       ).setParameter("username", username).getSingleResult();
    Querydsl is a framework which enables the construction of statically typed SQL-like queries via its fluent API.
    Several Spring Data modules offer integration with Querydsl via QueryDslPredicateExecutor.
    Predicate predicate = user.firstname.equalsIgnoreCase("dave")
     .and(user.lastname.startsWithIgnoreCase("mathews"));
    
    userRepository.findAll(predicate);

    Query by example is considered exactly what its name suggests: you give an example and the query is built on a match of the given fields.
    • Querying your data store with a set of static or dynamic constraints
    • Frequent refactoring of the domain objects without worrying about breaking existing queries
    • No support for nested/grouped property constraints like firstname = ?0 or (firstname = ?1 and lastname = ?2)
    • Only supports starts/contains/ends/regex matching for strings and exact matching for other property types
    ExampleMatcher matcher = ExampleMatcher.matching()
      .withMatcher("firstname", endsWith())
      .withMatcher("lastname", startsWith().ignoreCase());
    }
        @Query("SELECT t FROM Todo t where t.title = ?1 AND t.description = ?2")
        public Optional<Todo> findByTitleAndDescription(String title, String description);
         
        @Query(value = "SELECT * FROM todos t where t.title = ?0 AND t.description = ?1",
            nativeQuery=true
        )
        public Optional<Todo> findByTitleAndDescription(String title, String description);
    http://www.thoughts-on-java.org/jpa-21-how-to-implement-type-converter/
    @Converter
    public class ColorConverter implements AttributeConverter<Color, String>
    http://www.cherryshoetech.com/2016/05/jpa-json-serializationdeserialization.html
    Create a Converter Class that implements AttributerConverter. 
         @Convert(converter = JpaJsonDocumentsConverter.class)
         private List<JsonDocuments> documents;
    @Converter
    public class JpaJsonDocumentsConverter implements
            AttributeConverter<List<JsonDocuments>, String> {
    
        // ObjectMapper is thread safe
        private final static ObjectMapper objectMapper = new ObjectMapper();
    
        private Logger log = LoggerFactory.getLogger(getClass());
    
        @Override
        public String convertToDatabaseColumn(List<JsonDocuments> meta) {
            String jsonString = "";
            try {
                log.debug("Start convertToDatabaseColumn");
    
                // convert list of POJO to json
                jsonString = objectMapper.writeValueAsString(meta);
                log.debug("convertToDatabaseColumn" + jsonString);
    
            } catch (JsonProcessingException ex) {
                log.error(ex.getMessage());
            }
            return jsonString;
        }
    
        @Override
        public List<JsonDocuments> convertToEntityAttribute(String dbData) {
            List<JsonDocuments> list = new ArrayList<JsonDocuments>();
            try {
                log.debug("Start convertToEntityAttribute");
    
                // convert json to list of POJO
                list = Arrays.asList(objectMapper.readValue(dbData,
                        JsonDocuments[].class));
                log.debug("JsonDocumentsConverter.convertToDatabaseColumn" + list);
    
            } catch (IOException ex) {
                log.error(ex.getMessage());
            }
            return list;
        }
    }
    http://stackoverflow.com/questions/24367572/how-to-use-limit-in-spring-within-sql-query
    LIMIT is not part of JPQL. The mechanism available in current release version (1.6.0.RELEASE as of the time of writing) is pagination:
    interface PersonRepository extends Repository<Person, Long> {
    
      @Query("...")
      List<Person> findLimited(..., Pageable pageable);
    }
    This can then be used as follows:
    repository.findLimited(..., new PageRequest(0, 10));
    This will return the first ten results of the query defined in the @Query annotation.
    The current master branch of Spring Data JPA already contains a new feature that would allow you to rewrite above query as follows:
    interface PersonRepository extends Repository<Person, Long> {
    
      List<Person> findTop3ByCompanyOrderByName(Company company);
    }
    As of version 1.7.0.M1 (feature already available in snapshots) the query derivation mechanism will understand Top and First in the subject clause To limit the number of results returned.
    https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
    The results of query methods can be limited via the keywords first or top, which can be used interchangeably. An optional numeric value can be appended to top/first to specify the maximum result size to be returned. If the number is left out, a result size of 1 is assumed.
    User findFirstByOrderByLastnameAsc();
    
    User findTopByOrderByAgeDesc();
    
    Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
    
    Slice<User> findTop3ByLastname(String lastname, Pageable pageable);
    
    List<User> findFirst10ByLastname(String lastname, Sort sort);
    
    List<User> findTop10ByLastname(String lastname, Pageable pageable);
    The limiting expressions also support the Distinct keyword. Also, for the queries limiting the result set to one instance, wrapping the result into an Optional is supported.


    The results of query methods can be processed incrementally by using a Java 8 Stream<T> as return type. Instead of simply wrapping the query results in a Stream data store specific methods are used to perform the streaming.
    @Query("select u from User u")
    Stream<User> streamAllPaged(Pageable pageable);

    @Async
    Future<User> findByFirstname(String firstname);               
    
    @Async
    CompletableFuture<User> findOneByFirstname(String firstname); 
    
    @Async
    ListenableFuture<User> findOneByLastname(String lastname);    
    Use java.util.concurrent.Future as return type.
    Use a Java 8 java.util.concurrent.CompletableFuture as return type.
    Use a org.springframework.util.concurrent.ListenableFuture as return type
    http://springinpractice.com/2012/05/11/pagination-and-sorting-with-spring-data-jpa
        public Page<Deployment> getDeploymentLog(Integer pageNumber) {
            PageRequest request =
                new PageRequest(pageNumber - 1, PAGE_SIZE, Sort.Direction.DESC, "startTime");
            return deploymentRepo.findAll(pageRequest);
        }
    http://docs.spring.io/spring-data/jpa/docs/1.8.x/reference/html/#core.web
    https://www.petrikainulainen.net/spring-data-jpa-tutorial/
    https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-seven-pagination/
    If we want create the Pageable object manually, the service class (or other component) that wants to paginate the query results, which are returned by a Spring Data JPA repository, must create the Pageable object and pass it forward to the invoked repository method.
    We have to sort the query results in ascending order by using the values of the title and descriptionfields. If we want to get the second page by using page size 10, we have to create the Pageable object by using the following code:
    1
    2
    3
    private Pageable createPageRequest() {
        return new PageRequest(1, 10, Sort.Direction.ASC, "title", "description");
    }
    private Pageable createPageRequest() {
        return new PageRequest(1,
                10,
                new Sort(Sort.Direction.DESC, "description")
                        .and(new Sort(Sort.Direction.ASC, "title"));
        );
    }

    Using Spring Data Web Support

    We can enable Spring Data web support by annotating our application context configuration class with the @EnableSpringDataWebSupport annotation.

    @EnableSpringDataWebSupport
        @RequestMapping(value = "/api/todo/search", method = RequestMethod.GET)
        public Page<TodoDTO> findBySearchTerm(@RequestParam("searchTerm") String searchTerm,
                                              Pageable pageRequest) {
            return searchService.findBySearchTerm(searchTerm, pageRequest);
        }
    Page<Todo> findAll(Pageable pageRequest);

    http://stackoverflow.com/questions/13135309/how-to-find-out-whether-an-entity-is-detached-in-jpa-hibernate
    To find out whether an entity has been detached, we'd need to know whether it was previously managed (i.e. came from the database, e.g. by being persisted or obtained from a find operation). Hibernate doesn't provide an "entity state history" so the short answer is there isn't a 100% reliable way of doing this but the following workaround should be sufficient in most cases:
    public boolean isDetached(Entity entity) {
        return entity.id != null  // must not be transient
            && !em.contains(entity)  // must not be managed now
            && em.find(Entity.class, entity.id) != null;  // must not have been removed
    }
    http://stackoverflow.com/questions/23645091/spring-data-jpa-and-hibernate-detached-entity-passed-to-persist-on-manytomany-re
    I had the same problem and solved it by removing the cascade = CascadeType.PERSIST.
    In your case you use CascadeType.ALL, which is equivalent to also using the PERSIST, according to the documentation:
    Defines the set of cascadable operations that are propagated to the associated entity. The value cascade=ALL is equivalent to cascade={PERSIST, MERGE, REMOVE, REFRESH, DETACH}.
    It means when you try to save the reservation on reservationDAO.save(reservation) it will also try to persist the associated Product object. But this object is not attached to this session. So the error occur.
    entityManager.merge() is a good option. It will merge the detached objects in the session. No need to change any cascadeType.


    https://www.foreach.be/blog/spring-cache-annotations-some-tips-tricks
    Using @Cacheable combines both looking in the cache and storing the result. Using @CachePut and @CacheEvict annotations gives you more fine-grained control.  You can also use the @Caching annotation to combine multiple cache related annotations on a single method.  Avoid combining @Cacheable and @CachePut on the same method, as the behavior can be quite confusing.  But you can put them to some good use.
     @Caching(
          put = {
                @CachePut(value = "userCache", key = "'username:' + #result.username", condition = "#result != null"),
                @CachePut(value = "userCache", key = "#result.id", condition = "#result != null")
          }
     )
    https://enfernuz.blogspot.com/2016/09/spring-cacheable-annotation-and.html
    Since the version 4.3 the Spring's annotation @Cacheable has the option "sync" (by default set to "false") which, if being set to "true", does exactly that. But, as it's said in the documentation, "sync" option is just a hint and whether it's being supported or not is a matter of implementation. The Ehcache implementation in the spring-context-support module, which under the hood does use Ehcache 2.x, does not support this feature. So, what are the options left (besides the ones with using a proper implementation with support of "sync" feature)? To mark the @Cacheable target method as synchonized? It won't help -- in this case, the concurrent threads looking for the same key in the cache would just encounter a cache-miss in parallel, but then the invocations of the target method would be performed in a synchronized manner and still get the cache filled (and the unwanted task performed) more than once -- this is due to the fact that a cache-miss is happening earlier in the Spring cache facility and the actual target method's invocation is just a consequence of it.

    https://www.jianshu.com/p/1becdc376f5d
    时一个事务的多个操作需要在同一个Connection上。事务也往往是在业务逻辑层来控制

    ConnectionHolder
    在Spring中,有时候我们是不是要配置多个数据源DataSource?很显然,Spring需要通过DataSource来得到操作数据库的管道Connection,这有点类似于JNDI查找。
    这里通过ConnectionHolder类来完成这个过程,需要思考的是在多线程下,这显然是存在问题的。为避免多线程问题,难道我们采用线程安全的Map,比如ConcurrentHashMap,其实我们真正的目的是什么?是保证一个线程下,一个事务的多个操作拿到的是一个Connection,显然使用ConcurrentHashMap根本无法保证!
    SingleThreadConnectionHolder
    SingleThreadConnectionHolder
    本来线程不安全的,通过ThreadLocal这么封装一下,立刻就变成了线程的局部变量,不仅仅安全了,还保证了一个线程下面的操作拿到的Connection是同一个对象!这种思想,确实非常巧妙,这也是无锁编程思想的一种方式!

    Labels

    Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

    Popular Posts