运行时生成实体的通用JPA存储库

时间:2017-10-23 10:45:56

标签: spring generics spring-data-jpa spring-data-rest

在我的场景中,我在运行时在“com.mrg.domain”包下生成hibernate实体类。在我的通用restcontroller中,我可以根据@PathVariable创建这些实体的实例。下面的代码适用于此..

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

    Object model = null;    
    ObjectMapper mapper = new ObjectMapper();

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

        // Creating a new instance according to modelName
        Class<?> clazz = Class.forName("com.mrg.domain." + modelName);
        model = clazz.newInstance();

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

    } catch(Exception ex){

        // TODO handle exceptions & inform user..
    }   

    return new RestResponse(model.toString());
}

现在,我尝试实现的下一步是一个通用的jpa存储库(如下所示),这样我就可以持久化运行时生成的模型,而无需为每个实体实现存储库。但还是找不到解决方案。

@Repository
public interface GenericRepository<T> extends PagingAndSortingRepository<T, Long>{  }

下面的主题和许多其他主题实现了通用存储库,但也包含了使用通用存储库的每个实体的存储库。由于我有运行时生成的实体,每个实体的repo实现对我来说都不起作用..

How to make generic jpa repository? Should I do this? Why?

有任何建议或方法可以实现这一目标吗?我是仿制药和反思的新手,所以如果我想要完成的是不可能的,请告诉我原因,我会很感激..

谢谢和问候,

2 个答案:

答案 0 :(得分:1)

我有一个React应用程序,其中在JSON中定义了不同的数据,并且在服务器端,我需要将其存储在数据库中。我最初的方法是分别为此创建实体,存储库和控制器。但是,对于CRUD操作,另一种可能的方法是使用MongoDB和JPA。这是主意。

import java.util.List;

import org.bson.Document;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/generic")
@CrossOrigin(origins = { "*" })
public class GenericController {

    @Autowired
    private MongoTemplate mongoTemplate;

    @PostMapping
    public ResponseEntity<Document> addData(@RequestBody String data) {
        JSONObject jsonObject = new JSONObject(data);
        String documentName = jsonObject.getString("documentName");
        Document doc = Document.parse(data);
        Document insertedDoc = mongoTemplate.insert(doc, documentName);
        return new ResponseEntity<>(insertedDoc, HttpStatus.CREATED);

    }

    @GetMapping("/{documentName}")
    public List<Document> getData(@PathVariable String documentName) {
        List<Document> allData = mongoTemplate.findAll(Document.class, documentName);
        return allData;
    }

}

答案 1 :(得分:0)

您可以使用此模式。这个使用EJB但可以在Spring等中使用。

@Stateless
public abstract class AbstractRepository<T> {

@PersistenceContext
protected EntityManager em;

public abstract Class<T> getActualClass();

public T getSingleResult(Map<String, String> params) {

    // build querytext based on params
    TypedQuery<T> query = em.createQuery(queryText.toString(), getActualClass());
    ............
}
}

现在为实现类:

@Stateless
public class InputStreamRepository extends AbstractRepository<InputDataStream> {

@Override
public Class<InputDataStream> getActualClass() {
    return InputDataStream.class;
}

}

getActualClass方法将为您提供实体的类impl信息。