chytonpide
chytonpide

Reputation: 121

possible alternatives to @GeneratedValue with @EmbeddedId in JPA

My entity has a wrapped Identifier like this,

@Entity
public class Article {
   
   @EmbeddedId
   private ArticleId articleId;

   ....
}

@Embeddable
public class ArticleId implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

}

in my architecture, multiple application instances(it all same.) are connected to the same data source
so @GeneratedValue(strategy = GenerationType.IDENTITY)seems good
because even if instances A and B try to create Accountat the same time, Its Id is guaranteed by the database.

problem is that @GeneratedValue is only able to use with @Id annotation (@Id is not available for EmbeddedId)

PersistenceUnitUtil.getIdentifier(Object entity) could be a alternative? like this,

ArticleId articleId = ArticleRepository.nextIdentity();

I am not sure that whether it causes the race condition.
Could PersistenceUnitUtil.getIdentifier(Object entity) guarantee the unique id across the different application instance(JVM)? I don't think so.

In this situation, What alternative is possible?

Upvotes: 0

Views: 998

Answers (1)

fladdimir
fladdimir

Reputation: 1355

One solution could be to use an @IdClass to get rid of the nested property and be able to generate the identifier (since nested properties are "assigned" and cannot be generated, so the call of PersistenceUnitUtil.getIdentifier(Object entity) would not help here). See e.g. here for a complete guide (also linked in the linked answer by @SternK from the comment)

An @IdClass could look like this:

public class ArticleId implements Serializable {
  private Long id;
}

An entity could use it:

@Entity
@IdClass(ArticleId.class) // specified dependency
public class Article {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  private Long id;

  // expose "typed" id:
  public ArticleId getId() {
    return new ArticleId(id);
  }
}

Spring-Data @Repositorys also work with corresponding @IdClass objects, e.g.:

@Repository
public interface UserEntityRepository extends JpaRepository<Article, ArticleId> {
}

// would offer e.g. this method:
repository.findById(new ArticleId(123L));

Upvotes: 1

Related Questions