I am trying to use JPA to fetch records from database. However I am able to insert records indatabse and even get all the records using createQuery method of class EntityManager.
But in below case I am not getting why the condition in where clause is not working.
Please help me figure it out.
POJO class :
#Entity
#Table(name = "frameworks_filter")
public class FilteredFrameworksDbStructure {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "regular_name")
private String regularName;
#Column(name = "component_name")
private String componentName;
#Column(name = "component_owner")
private String componentOwner;
#Column(name = "frameworks")
private String frameworks;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRegularName() {
return regularName;
}
public void setRegularName(String regularName) {
this.regularName = regularName;
}
public String getComponentName() {
return componentName;
}
public void setComponentName(String componentName) {
this.componentName = componentName;
}
public String getComponentOwner() {
return componentOwner;
}
public void setComponentOwner(String componentOwner) {
this.componentOwner = componentOwner;
}
public String getFrameworks() {
return frameworks;
}
public void setFrameworks(String frameworks) {
this.frameworks = frameworks;
}
}
DAO class method:
public List<FilteredFrameworksDbStructure> getFilteredFrameworks(String regularName) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
List<FilteredFrameworksDbStructure> filteredFrameworksDbStructureList = entityManager
.createQuery("from FilteredFrameworksDbStructure F where F.regularName = :regular", FilteredFrameworksDbStructure.class)
.setParameter("regular", regularName)
.getResultList();
return filteredFrameworksDbStructureList;
}
Issue : Condition in where clause does not work. It simply fetch all the records irrespective of the regularName provided.
Regards,
Parag Vinchurkar
Why don't you use the JpaRepository or CrudRepository to fetch your results? Check out this tutorial here and here on how to use them.
And you can use your where clause. Please see below the example repository you can use to obtain the same results as the entityManager
public interface FilteredFrameworksDbStructureRepo extends JpaRepository<FilteredFrameworksDbStructure , Integer>{
List<FilteredFrameworksDbStructure> findAllByRegularName(String regularName)
}
Please note that you will have to change your id member variable from int to Integer
I am working on a project with GraphQL-java and Hibernate with MariaDB.
In my current solution, I get 18938 results back. I just want to see the last 10 of these. So I am looking for a solution to limit the number of results.
On the internet I see examples of limiting the number of results (https://graphql.org/learn/pagination/). They call it pagination. However, I cannot find the server implementation of this. Does anyone have experience with this?
I have an Entity class, with some properties : Test.java
#Entity
#Table(name = "test")
public class Test {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Size(max = 64)
#Column(nullable = false)
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "parent")
private Test parent;
public Test() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Test getParent() {
return parent;
}
public void setParent(Test parent) {
this.parent = parent;
}
My repository class: TestRepository.java
public interface TestRepository extends CrudRepository<Test, Integer> {}
My GraphQL resolver class: Query.java
#Component
public class Query implements GraphQLQueryResolver {
private TestRepository testRepository;
#Autowired
public Query(TestRepository testRepository) {
this.testRepository = testRepository;
}
public Iterable<Test> findAllTests(Integer first) {
return testRepository.findAll();
}
public long countTests() {
return testRepository.count();
}
}
My GraphQL schema: test.graphqls
type Test {
id: ID!
name: String!
parent: Test
}
#extend query
type Query {
findAllTests(first: Int): [Test]!
countTests: Int!
}
To summarize my last comment here is what I would do:
Instead of extending CrudRepository, extend PagingAndSortingRepository (which is extending CrudRepository)
public interface TestRepository extends PagingAndSortingRepository<Test, Integer> {
}
In your Query class pass two args to findAllTests method, page and size that will be used to create the Pageable object
#Component
public class Query implements GraphQLQueryResolver {
// other properties & methods are omitted for brevity
public Iterable<Test> findAllTests(Integer page, Integer size) {
Pageable pageable = PageRequest.of(page, size);
return testRepository.findAll(pageable).getContent(); // findAll returns Page and we can get the underlying List with getContent
}
}
Add two params from above in your GraphQL schema (I set default page size to be 20)
#extend query
type Query {
findAllTests(page: Int = 0, size: Int = 20): [Test]!
countTests: Int!
}
Since I have no experience with GraphQL, I'm not sure if this works, but you can give me feedback if there are some problems.
I have a spring boot (1.5.4.RELEASE) project using Java 8. I have an entity and it's related domain class like this:
#Entity
#Table(name = "Foo", schema = "dbo")
public class FooEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id")
private int id;
#Column(name="Name")
private String name;
#Column(name="Type")
private String type;
#Column(name="Color")
private String color;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "Car")
private Car car;
//getter and setter
}
public class Foo {
private int id;
private String name;
private String type;
private String color;
private Car car;
//Constructors and getters
}
I want to create a repository that fetches this Foo object from the DB but only fetching the complex fields if the user asks for them to prevent unnecessary join statements. The repo looks like this:
import static com.test.entities.QFooEntity.fooEntity;
import static com.test.entities.QCarEntity.carEntity;
#Repository
public class FooRepository {
private final JPAQuery<FooEntity> query = createQuery().from(fooEntity);
public FooRepository getFooByName(String name) {
query.where(fooEntity.name.eq(name));
return this;
}
public FooRepository withCar() {
query.leftJoin(fooEntity.car, carEntity).fetchJoin();
return this;
}
public Foo fetch() {
FooEntity entity = query.fetchOne();
return FooMapper.mapEntityToDomain().apply(entity);
}
}
So a barebones call for a Foo object will return the Entity with values for all the fields except for the car field. If the user wants car information then they have to explicitly call withCar.
Here is the mapper:
public class FooMapper {
public static Function<FooEntity, Foo> mapEntityToDomain() {
return entity -> {
return new Foo(e.getId(), e.getName(), e.getType(), e.getColor(), e.getCar());
};
}
}
The problem is when you do e.getCar() if the value is not there (i.e. there's a proxy present) JPA will go out and fetch it for you. I don't want this to be the case. It will just grab the values and map them to the domain equivalent if it's not there then null.
One solution that I've heard (and tried) is calling em.detach(entity); however, this doesn't work as I intended because it throws an exception when you try to access getCar and I've also heard this is not best practice.
So my question is what is the best way to create a repo using a builder pattern on a JPA entity and not have it call the DB when trying to map.
You could create a utility method that will return null if the given object is a proxy and is not initialized:
public static <T> T nullIfNotInitialized(T entity) {
return Hibernate.isInitialized(entity) ? entity : null;
}
Then you can call the method wherever you need it:
return new Foo(e.getId(), e.getName(), e.getType(), e.getColor(), nullIfNotInitialized(e.getCar()));
Just map it to a new object and leave out the Car relation, this is the standard approach. You can use MapStruct and just ignore the car field during mapping: http://mapstruct.org/documentation/stable/reference/html/#inverse-mappings
Just don't map the car... Map a field holding the ID and use another method to get the actual Car. I would use a distinctive method name, to differentiate it from the other getters.
class FooEntity {
#Column
private int carId;
public int getCarId() {
return carId;
}
public void setCarId(int id) {
this.carId = id;
}
public Car fetchCar(CarRepository repo) {
return repo.findById(carId);
}
}
You can write query on top of JPA
#Query("select u from Car c")
import org.springframework.data.repository.CrudRepository;
import com.example.model.FluentEntity;
public interface DatabaseEntityRepository extends CrudRepository<FooEntity , int > {
}
As you said
I don't want this to be the case. It will just grab the values and map them to the domain equivalent, if it's not there then null.
Then you just set it to null, because the field car will always not be there.
Otherwise, if you mean not there is that the car not exists in db, for sure a subquery(call the proxy) should be made.
If you want to grab the car when call Foo.getCar().
class Car {
}
class FooEntity {
private Car car;//when call getCar() it will call the proxy.
public Car getCar() {
return car;
}
}
class Foo {
private java.util.function.Supplier<Car> carSupplier;
public void setCar(java.util.function.Supplier<Car> carSupplier) {
this.carSupplier = carSupplier;
}
public Car getCar() {
return carSupplier.get();
}
}
class FooMapper {
public static Function<FooEntity, Foo> mapEntityToDomain() {
return (FooEntity e) -> {
Foo foo = new Foo();
foo.setCar(e::getCar);
return foo;
};
}
}
Make sure you have the db session ,when you call Foo.getCar()
You could try adding state to your repository and influence the mapper. Something like this:
import static com.test.entities.QFooEntity.fooEntity;
import static com.test.entities.QCarEntity.carEntity;
#Repository
public class FooRepository {
private final JPAQuery<FooEntity> query = createQuery().from(fooEntity);
private boolean withCar = false;
public FooRepository getFooByName(String name) {
query.where(fooEntity.name.eq(name));
return this;
}
public FooRepository withCar() {
query.leftJoin(fooEntity.car, carEntity).fetchJoin();
withCar = true;
return this;
}
public Foo fetch() {
FooEntity entity = query.fetchOne();
return FooMapper.mapEntityToDomain(withCar).apply(entity);
}
}
In your mapper, you then include a switch to enable or disable car lookups:
public class FooMapper {
public static Function<FooEntity, Foo> mapEntityToDomain(boolean withCar) {
return e -> {
return new Foo(e.getId(), e.getName(), e.getType(), e.getColor(), withCar ? e.getCar() : null);
};
}
}
If you then use new FooRepository().getFooByName("example").fetch() without the withCar() call, e.getCar() should not be evaluated inside FooMapper
You may want to use the PersistentUnitUtil class to query if an attribute of entity object is already loaded or not. Based on that you may skip the call to corresponding getter as shown below. JpaContext you need to supply to user entity bean mapper.
public class FooMapper {
public Function<FooEntity, Foo> mapEntityToDomain(JpaContext context) {
PersistenceUnitUtil putil = obtainPersistentUtilFor(context, FooEntity.class);
return e -> {
return new Foo(
e.getId(),
e.getName(),
e.getType(),
e.getColor(),
putil.isLoaded(e, "car") ? e.getCar() : null);
};
}
private PersistenceUnitUtil obtainPersistentUtilFor(JpaContext context, Class<?> entity) {
return context.getEntityManagerByManagedType(entity)
.getEntityManagerFactory()
.getPersistenceUnitUtil();
}
}
Below is the DAO. I am getting the first UppeningUsers object. Note that here for this function I do not want to return peopleWhoBlockedMe set which is located inside the UppeningUsers..
But in different functions I would like to return that information. Note that Both of them are LAZY fetching. With evict I tried to detach the object but still it did not work.
First of all RESTcontroller is below. Then the DAO code is below. Then two entity descriptions are below.
Question is: I see that until
return new ResponseEntity(returned, HttpStatus.OK);
There is only one query which is the typical select. I do not want hibernate to go and take also UserBlock information of that specific UppeningUser. Because it is not needed for this service response. However even though it is lazy loading for some reason
return new ResponseEntity(returned, HttpStatus.OK);
calls the hibernate. I dont know why in restcontroller still it is connected to the database. I tried evict but didnt work.
The json response is
{"id":7,"peopleWhoBlockedMe":[{"blockedId":7}]}
But I do not want for this function to return this peopleWhoBlockedMe. It can be empty.
PLEASE NOTE that in other service for example I will explictly request this peopleWhoBlockedMe but just for this business logic I do not need this information. So what I can do to prevent this so whenever I actually want to call peopleWhoBlockedMe I can get it. Not automaticly.
#RestController
public class TempController {
#Autowired
UppeningUsersService uppeningUsersService;
#RequestMapping(value = "/testing", method = RequestMethod.GET)
public ResponseEntity<UppeningUsers> getPhotos() {
try {
UppeningUsers returned = uppeningUsersService.getUsersDetailsPartial();
return new ResponseEntity<UppeningUsers>(returned, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
This part is the DAO.
#Repository
public class UppeningUsersDAO {
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf) {
this.sessionFactory = sf;
}
/**
* Get Existing user. Return error if there is not.
* #param incomingUser user who requested access.
* #return returns the guy information. All information.
*/
#Transactional
public UppeningUsers getUserDetails() throws Exception {
Session session = this.sessionFactory.getCurrentSession();
Query query = session.createQuery("from UppeningUsers ");
UppeningUsers returning = (UppeningUsers) query.list().get(0);
session.evict(returning);
return returning;
}
}
The main table is this one..
#Entity
#Table(name = "uppening_users")
#Proxy(lazy = true)
public class UppeningUsers {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private
int id;
#OneToMany(mappedBy = "blockedId",cascade =CascadeType.ALL, fetch = FetchType.LAZY)
private Set<UserBlocks> peopleWhoBlockedMe;
public UppeningUsers() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Set<UserBlocks> getPeopleWhoBlockedMe() {
return peopleWhoBlockedMe;
}
public void setPeopleWhoBlockedMe(Set<UserBlocks> peopleWhoBlockedMes) {
this.peopleWhoBlockedMe = peopleWhoBlockedMes;
}
}
Now here is the other table.
#Entity
#Table(name="user_blocks")
#Proxy(lazy = true)
public class UserBlocks {
#Id
#Column(name="id")
#GeneratedValue(strategy= GenerationType.IDENTITY)
int id;
#Column(name = "blocked_id",insertable = false,updatable = false)
private int blockedId;
public int getBlockedId() {
return blockedId;
}
public void setBlockedId(int blockedId) {
this.blockedId = blockedId;
}
}
UPDATE: 2 forgot to add the service
#Service("uppeningUserService")
public class UppeningUsersService {
#Autowired
UppeningUsersDAO uppeningUsersDAO;
public UppeningUsers getUsersDetailsPartial( ) throws Exception {
return uppeningUsersDAO.getUserDetails();
}
}
Jens is right about her sentence. The layer methodology and writing business objects fix the issue. Thank you.
Environment:
spring-data-mongo: 1.7.0.RC1
mongo-java-driver: 3.2.2
Document:
#Document(collection = "products")
public class Product {
#Id
private String sid;
private String name;
private Long vendor;
(...)
}
Repository:
public interface ProductRepository extends MongoRepository<Product, String> {
Product findByName(String productName);
}
My goal is to intercept any query performed on the Product collection and add a predicate or a specification without modifying the repository or the need to implement the method findByNameAndBelongsToVendorList.
I need this interceptor or aspectJ because I have multiple methods like:
Page<Product> findAll(Pageable page);
List<Product> findByCategory(String category, Pageable pageRequest);
(...)
Goal
findByName // perform a filter by name (explicit)
// and a filter by vendor (injected via inteceptor or aspecJ)
Avoid doing this
#Repository
public class ProductRepositoryCustomImpl implements ProductRepositoryCustom {
#Autowired
private MongoTemplate template;
public Product findByNameAndBelongsToVendorList(String name, List<Long> vendors, Pageable pageRequest) {
Criteria criteriaVendor = Criteria.where("vendors").in(vendors);
Query query = new Query(criteriaVendor);
query.with(pageRequest);
return template.findOne(query, Product.class);
}
}
Aspects should do the trick.
#Aspect
public class YourAspect {
#Autowired
private MongoTemplate template;
#Pointcut("execution(public * findByName(..))")
private void findByName() {
}
#Pointcut("within(com.leonel.repository.ProductRepository)")
private void repository() {
}
#Around("repository() && findByName()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
String name = (String) args[0];
Criteria newCriteria = YOUR NEW LOGIC HERE;
Query query = new Query(newCriteria);
return template.find(query, Your.class);
}
I would recommend against it though, as it introduces a bit of magic to your code and manipulating queries should not be a concern of aspects.
What is the reason you want to avoid having multiple find methods in your repository?