Tag: spring-boot

Upgrading my blog to Spring Boot 2.0

Spring Boot 2.0 was finally released on May 1, 2018, and my blog has been upgraded to it from Spring Boot 1.5.9.

Spring Boot 2.0 is a major update of 17 months' work. It breaks some configurations due to refactoring and dependency updates along with it.

Package removable/rename:

  • spring-boot-starter-mobile starter is removed.
  • spring-session should be replaced by spring-session-data-redis.

Gradle plugin updates:

  • Dependency management plugin is no longer automatically applied, and should be explicitly enabled.
  • The bootRepackage task is replaced by bootJar, and as a result jar task is no longer not invoked when building executable jars. This breaks configuration for jar task.

Dependency updates:

  • Hibernate validator from 5.3.6 to 6.0.7: org.hibernate.validator.constraints.NotEmpty is deprecated and javax.validation.constraints.NotEmpty should be used.
  • Flyway: Spring Boot's default flyway.table has been changed from schema_version to flyway_schema_history.
  • spring-data-commons from 1.13 to 2.0: Configuration for 1-based pagination has to be changed.

Refactoring:

  • AbstractErrorController, ErrorViewResolver are moved from package org.springframework.boot.autoconfigure.web to org.springframework.boot.autoconfigure.web.servlet.error.
  • FreeMarkerAutoConfiguration.FreeMarkerWebConfiguration is replaced by a package-private class, breaking the configuration that extends the class.
Read more >>

JPA many-to-many update efficiency

When updating many-to-many relationships, the SQL executed by JPA may be quite inefficient.

Suppose we have a Post-Tag association: each post can have multiple tags, and each tag can also has multiple posts.

postidtagidpost_tagidpost_idtag_id

Java code:

// Post.java
@Entity
public class Post {
  @Id
  private Integer id;
  
  @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
  @JoinTable(
    name = "post_tag",
    joinColumns = @JoinColumn(name = "post_id"),
    inverseJoinColumns = @JoinColumn(name = "tag_id")
  )
  private List<Tag> tags = new ArrayList<>();

  // getters and setters

  public void addTag(Tag tag) {
    tags.add(tag);
    tag.getPosts().add(this);
  }

  public void removeTag(Tag tag) {
    tags.remove(tag);
    tag.getPosts().remove(this);
  }
}

// Tag.java
@Entity
public class Tag {
  @Id
  private Integer id;
  
  @ManyToMany(mappedBy = "tags")
  private List<Post> posts = new ArrayList<>();

  // getters and setters
}

Suppose a post(id = 1) has two tags(id = 1, 2). When adding a new tag(id = 3) to the post, JPA may issue the following SQL:

DELETE FROM post_tag WHERE post_id = 1;
INSERT INTO post_tag(post_id, tag_id) VALUES (1, 1);
INSERT INTO post_tag(post_id, tag_id) VALUES (1, 2);
INSERT INTO post_tag(post_id, tag_id) VALUES (1, 3);

While inserting a single record is enough, it at first deletes all existing association records, and then creates all "new" association records. Same problems applies when deleting tags from the post.

It's quite inefficient. And if you have additional columns ("createdAt" for example) in the association table, or you have some triggers based on inserting/deleting association records, you may encounter some problems.

How to solve this problem? There may be two solutions.

Read more >>

My own blog built with Spring Boot

I have been planning to build my own blog (previously it was powered by WordPress) for a long time, and now it finally comes.

The new blog is build with Spring Boot.

Why Spring Boot? Because I have switched to Java for several months. In addition to powering my blog site, the new blog also serves as a learning project.

In addition to Spring Boot, it also uses the following technologies or services:

Source code is available on GitHub.

The features are quite limited for now, but it will be iterated gradually.

Read more >>