3

In my SpringBoot application i'm generating hibernate entity classes and repositories using javapoet and than compiling these generated source files respectively using OpenHFT library at runtime. My purpose is being able to persist these runtime generated entities.

I could successfully use this generated entity inside my rest controller and map @RequestBody json String to this entity. But my problem is i couldn't inject my runtime generated repository to the controller..

Here is an example runtime generated entity;

@Entity
public class Author extends BaseEntity{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private Long id;
    private String firstName;
    private String lastName;

    public Author(){
        super();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

Here is the runtime generated repository for above entity

import org.springframework.stereotype.Repository;
import java.lang.Long;
import com.mrg.domain.Author;

@Repository("authorRepository")
public interface AuthorRepository extends GenericRepository<Author, Long> {

}

Here is the generic repository i'm using so that i can inject my repos at runtime

@NoRepositoryBean
public interface GenericRepository<T, ID extends Serializable  > extends PagingAndSortingRepository<T, ID>{

}

And below is my rest controller. Here im autowiring generic repository as a Map so that Spring is injecting correct repository implementation dynamically when i use it with repository name as a key;

genericRepo.get(repoName).save(model);

@RestController
@RequestMapping("/{entity}")
public class GenericRestController {


    @Autowired
    private Map<String, GenericRepository> genericRepo;

    @RequestMapping(value = "/{entity}/", method = RequestMethod.POST)
    public @ResponseBody Object createEntity(@PathVariable String entity, @RequestBody String requestBody) {

        Object model = null;
        ObjectMapper mapper = new ObjectMapper();
        String repoName = "";

        try {

            // ex : if {entitiy} param is equal "author" modelName will be "Post"
            String modelName = Character.toUpperCase(entity.charAt(0)) + entity.substring(1);

            Class<?> clazz = Class.forName("com.mrg.domain." + modelName);
            model = clazz.newInstance();

            // Converting @RequestBody json String to domain object..
            model = mapper.readValue(requestBody, clazz);

            // Repository name is {entity} + "Repository" ex : authorRepository
            repoName = entity.concat("Repository");

        } catch (Exception ex) {

            // handling exceptions..
        }
        // Saving with right repository 
        return genericRepo.get(repoName).save(model);
    }
}

This is working for repositories that i wrote manually and i can persisting objects with this approach dynamically. But i couldnt access my runtime generated repositories.(genericRepo.get("authorRepository") is returning null reference)

Could you suggest a solution for this problem. What am i missing here? Any other idea for persisting runtime generated objects would be helpfull.

Thanks..

4

2 回答 2

1

最近,我遇到了类似的情况,必须在运行时生成 Repository 以减少样板代码。通过一些研究,事实证明,在扫描带有 @Repository 注释的接口时,它使用 ClassPathScanningCandidateComponentProvider,它扫描类路径中的类,忽略运行时生成的类。

于 2019-05-08T07:05:27.543 回答
0

您的存储库位于一个包中,例如 com.mypackage.repository。在您的配置中,您应该扫描这个包(以及带有控制器的包),以便 Spring 了解这些 bean:

@Configuration
@ComponentScan(value = {"com.mypackage.controller"})
@EnableJpaRepositories(basePackages = {"com.mypackage.repository"})
public class MyConfig {
    // creation and configuration of other beans
}

Config 类可能有更多用于您自己目的的注释(例如,@EnableTransactionManagement、@PropertySource 用于文本文件中的道具)。我只是发布了一组强制性的注释。

于 2017-10-31T08:03:06.973 回答