Reputation: 348
In my scenario im generating hibernate entity classes at runtime under "com.mrg.domain" package. And in my generic restcontroller i can create instances of these entities according to @PathVariable. Below code works fine for this..
@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());
}
Now the next step i am trying to implement is a generic jpa repository(something like below) so that i can persist runtime generated models without implementing repositories for each entity. But couldn't find a solution yet.
@Repository
public interface GenericRepository<T> extends PagingAndSortingRepository<T, Long>{ }
Below topic and many other topics implemented generic repositories but also repositories per entities that uses generic repo. Since i have runtime generated entities repo implementation per entity doesnt work for me..
How to make generic jpa repository? Should I do this? Why?
Any suggestion or a way for achieving this? I'm new to generics and reflection so if what im trying to accomplish is not possible, tell me reasons and i would be appreciate..
Thanks and regards,
Upvotes: 0
Views: 1184
Reputation: 5297
I had a react application where different data is defined in JSON and in the server side, I need to store this in the DB. My initial approach was to create entities , repositories and controller for all of this seperately. But another possible approach for CRUD operation is with MongoDB & JPA. Here is the idea.
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;
}
}
Upvotes: 1
Reputation: 2109
You could use this pattern. This one uses EJB but can be used in Spring etc.
@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());
............
}
}
Now for the implementation class:
@Stateless
public class InputStreamRepository extends AbstractRepository<InputDataStream> {
@Override
public Class<InputDataStream> getActualClass() {
return InputDataStream.class;
}
}
The getActualClass method will give you the Entity's class impl info.
Upvotes: 1