Home > Net >  One method to save entity which extand abstract class in repository
One method to save entity which extand abstract class in repository

Time:09-22

I am new at abstract class as Entity so for training I created abstract class

@Entity
@Inheritance(strategy = TABLE_PER_CLASS)
@Getter
@Setter
@NoArgsConstructor
public abstract class ShapeEntity {
     @Id
     @GeneratedValue(generator = "system-uuid")
     @GenericGenerator(name = "system-uuid", strategy = "uuid")
     private String id = UUID.randomUUID().toString();
}

and classes which extand Shape:

public class SquareEntity extends ShapeEntity {
    ...
}
public class CircleEntity extends ShapeEntity {
    ...
}

every entity has repostiory like that:

public interface CircleEntityRepository extends JpaRepository<CircleEntity, String> {
}

When I want to update entity I am searching it in every repository, next (if entity was found) map parameters and finnaly have to save that entity in database. How can I easy decide which repository should be used for it? I created method save with if else which now works:

public ShapeEntity save(ShapeEntity shapeEntity) {
    if (shapeEntity.getClass().getName().contains("CircleEntity")) {
        return circleEntityRepository.save((CircleEntity) shapeEntity);
    } else if (shapeEntity.getClass().getName().contains("SquareEntity")) {
        return squareEntityRepository.save((SquareEntity) shapeEntity);
    } else {
        throw new EntityNotFoundException();
    }
}

but it is a bit uncomfortable becouse when I will have 20 entities I will have to create 20 else if loops. Can I do any interface for this or something like that?

CodePudding user response:

If you create a ShapeEntityRepository for the ShapeEntity class you don't need if-else blocks.

public interface ShapeEntityRepository
        extends JpaRepository<ShapeEntity, String>, 
        JpaSpecificationExecutor<ShapeEntity> {}

ShapeEntityRepository is useable for all classes that are extended from the ShapeEntity class.

ShapeEntity circleEntity = new CircleEntity();
ShapeEntity squareEntity = new SquareEntity();

shapeEntityRepository.save(circleEntity);
shapeEntityRepository.save(squareEntity);

Alternatively, if there must be different repositories, you can use Spring's GenericTypeResolver to get the repository of the class.

@Component
public class RepositoryHolder {

    private final List<JpaRepository> jpaRepositories;

    public RepositoryHolder(List<JpaRepository> jpaRepositories) {
        this.jpaRepositories = jpaRepositories;
    }

    public JpaRepository getRepositoryBy(Class<?> domainClass) {
        Optional<JpaRepository> optionalRepository = jpaRepositories.stream()
                .filter(repository -> GenericTypeResolver
                        .resolveTypeArguments(
                                repository.getClass(),
                                Repository.class
                        )[0]
                        .equals(domainClass))
                .findFirst();
        if (optionalRepository.isPresent()) {
            return optionalRepository.get();
        } else throw new IllegalArgumentException();
    }
}

If you want to use it, your save(...) method will be something like this:

public void save(ShapeEntity shapeEntity) {
    JpaRepository repository = repositoryHolder
            .getRepositoryBy(shapeEntity.getClass());
    repository.save(shapeEntity);
}

Note: JPA Repository allows to use default CRUD functions, you can add an intermediate repository bean like here and reduce these codes to that intermediate repository.

  • Related