How to handle PropertyReferenceException - spring

I have reffered to various sources but my issue still did not solve,
Custom Repository
public interface BaseRepositoryCustom<ContactDTO,Long> {
List<ContactDTO> getTestData(String name);
}
Impl
public class BaseRepositoryImpl implements BaseRepositoryCustom {
#PersistenceContext
private EntityManager entityManager;
#Override
public List<ContactDTO> getTestData(String name) {
List<ContactDTO> contact = entityManager.createQuery("select * from COM_CONTACT").getResultList();
System.out.println(contact.size());
return null;
}
Main repository
public interface ConContactRepository extends JpaRepository<Contact, Long>,BaseRepositoryCustom {
List<ComContact> getTestData(String name);
}
I will get list of DTO as my result where was my main Repository is Contact type, how can i solve this issue
Exception
... 18 common frames omitted
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property getTestData found for type ComContact!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:235)
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:373)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:353)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:84)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:61)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:94)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:205)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:72)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:369)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:192)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:225)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
... 28 common frames omitted
Contact DTO
public class ContactDTO {
private String serviceName;
private String contactName;
private String title;
}
Contact domain model
#Entity
#Table(name = "COM_CONTACT", schema = "JMS_SCHEMA")
public class ComContact implements java.io.Serializable {
private long id;
private String serviceNm;
private String contactNm;
private String title;
private long fkTemplateId;
private Character mailFlag;
private String mailAddress;
private Character faxFlag;
private String faxNr;
}

First of all you don't need BaseRepositoryCustom.
You said you're using Spring Data JPA.
If you annotate your ConContactRepository with #Repository.
The class ComContact doesn't have a property "name", so lets assume you want to return all ComContact objects where serviceNm equals "xxx".
In your repository, create a method called FindAllByServiceNm (String serviceNm) and it should work, no SQL needed.
If you want to get all records, try findAll and it should work.
Once you get the records you want, you may convert them into ContactDTO objects, if applicable.

public interface ConContactRepository extends JpaRepository<Contact, Long>, ConContactRepositoryCustom {
List<ContactDTO> getTestData(String name);
}
public interface ConContactRepositoryCustom {
List<ContactDTO> getTestData(String name);
}
public class ConContactRepositoryImpl implements ConContactRepositoryCustom {
#PersistenceContext
private EntityManager entityManager;
#Override
public List<ContactDTO> getTestData(String name) {
List<ContactDTO> contact = entityManager.createQuery("select * from COM_CONTACT").getResultList();
System.out.println(contact.size());
return null;
}
}

Related

Modifying spring data repository methods (mongo)

I have the following classes: MyEntity, MyEntityRepository, MyEntityCustomRepository, MyEntityCustomRepositoryImpl.
MyEntity:
#Document
class MyEntity {
#Id
private ObjectId id;
private final String name;
#JsonIgnore
private Boolean isDeleted = false;
#JsonIgnore
private Instant deletedAt;
}
MyEntityRepository:
#Repository
interface MyEntityRepository extends MongoRepository<MyEntity, ObjectId>, MyEntityCustomRepository {}
MyEntityCustomRepository:
public interface MyEntityCustomRepository {
List <MyEntity> someCustomMethod(Set<ObjectId> ids);
}
MyEntityCustomRepositoryImpl
class MyEntityCustomRepositoryImpl implements MyEntityCustomRepository {
private final MongoTemplate template;
MyEntityCustomRepositoryImpl(MongoTemplate template) {
this.template = template;
}
#Override
public List <MyEntity> someCustomMethod(Set<ObjectId> ids) {
Query query = new Query()
...
return template.find(query, MyEntity.class);
}
}
Now I want to modify all find/get/count etc methods in the MyEntityRepository by adding param Criteria.where("isDeleted).is(false) to all queries.
It's easy to add this query param to my custom method, but what will be the best way to override methods from the CrudRepository extended by the MyEntityRepository?

Spring Data JPA Redis : Cannot write custom method based query

I have configured Spring Data JPA with Redis and using RedisRepositories with provides methods like find(), findAll() etc. All these methods seem to be working just fine, but I am not able to write my custom method like.
RedisEntity findByGenderAndGrade(String gender, String grade);
RedisEntity is a simple POJO Entity class. If you want any more info, please let me know in messages.
Following is my entity:
#Data
#RedisHash("test1")
public class RedisEntity implements Serializable {
#Id
#GeneratedValue
private String id;
private String name;
private String gender;
private Integer grade;
}
Repository:
#Repository
public interface TestRepository extends JpaRepository<RedisEntity, String> {
List<RedisEntity> findAllByGender(String gender);
List<RedisEntity> findAllByGrade(Integer grade);
}
Service/Controller:
#Override
public List<RedisEntity> getById(String id) {
return testRepository.findById(id); //returns data perfectly.
}
#Override
public List<RedisEntity> getAllByGender(String gender) {
return testRepository.findAllByGender(gender); //returns []
}
#Override
public void saveEntity(RedisEntity redisEntity) {
testRepository.save(redisEntity); // saves it in redis perfectly.
}
Also,
findByGender and findAllByGender both give [], although I can see data in my redis database and save it as well.
As requested by FrançoisDupire,
#Configuration
public class RedisConfig {
#Autowired
private DeploymentProperties deploymentProperties;
private static Logger logger = LoggerFactory.getLogger(RedisConfig.class);
#Bean
JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6379);
redisStandaloneConfiguration.setPassword(RedisPassword.of("root"));
return new JedisConnectionFactory(redisStandaloneConfiguration);
}
#Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
}
Also, I had referred this article: Baeldung article on Spring data redis
As mentioned by #JoshJ and verified by myself and others,
The solution to the problem is:
Adding #Indexed annotation
to all those columns/fields which need to be used with all finds.
#Data
#RedisHash("EmployeeDetails")
public class RedisEntity {
#Id
private String employeeId;
private String firstName;
private String lastName;
#Indexed
private String gender;
#Indexed
private String grade;
}
We have the Spring Data Redis Library which provides the scope to write the custom method.Attaching Sample code.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
Entity Definition
#Data
#RedisHash("EmployeeDetails")
public class RedisEntity {
#Id
private String employeeId;
private String firstName;
private String lastName;
private String gender;
private String grade;
}
Repository Definition
#Repository
public interface RedisEntityRepository extends CrudRepository<RedisEntity, String>{
List<RedisEntity> findAllByGenderAndGrade(String gender, String grade);
}
Implementation
#Component
public class RedisEntityImpl implements RedisEntityService {
#Autowired
private RedisEntityRepository redisEntityRepository;
#Override
public List<RedisEntity> getAllByGenderAndGrade(String gender, String grade) {
return redisEntityRepository.findAllByGenderAndGrade(gender,grade);
}
}
Properties
spring.cache.type = redis
spring.redis.host = localhost
spring.redis.port = 6379

Spring: Method Injection Lookup How to use it?

Can I use Method Injection Lookup -- with a entity class?.I use Spring+JPA+Hibernate. This allow to inject a prototype bean into a singleton bean.Is this also possible with entity beans?A is prototype scoped bean.I want to put A(#Entity) into a class B (ex. DAO) with scope=singleton.Thanks
#Entity
public class A(){
private String name;
private String surname;
...//get and set
}//A
public interface DAO{
public void method();
}//DAO
public class DAOImpl implements DAO{
private A object_a;
public void method(){
//In this method I use everytime a new istance of A
}//method
}//DAOImpl
You can use #Embedded to include your sub bean, and use in your sql.
#Entity
public class User(){
private String name;
#Embedded
private Address address;
#Bean(scope=DefaultScopes.PROTOTYPE)
public User() {
}
...//get and set
}
#Entity
public class Address(){
private String name;
...//get and set
}
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "select u from users u where u.address.name = :addressName")
List<Blog> findUserByAddress(#Param("addressName") String addressName);
}

Generic DAO design-pattern with inheritance. is this a good design?

I just want to have a comment for what I've learned from dozens of samples about Generic DAO design-pattern. I added an inheritance hierarchy between POJO classes, DAO interfaces, and DAO implementations please see codes below
Legend:
DAOs (From Parent to children)
DAO implementations (From Parent to Children)
POJO classes (From Parent to Children)
The Data Acess Objects (Interfaces)
The GenericDAO interface
public interface GenericDAO<T> {
... some crud operations common to all objets
}
The PersonDAO interface
public interface PersonDAO<T extends Person> extends GenericDAO<T> {
... some operations unique to a person
}
The StudentDAO interface
public interface StudentDAO extends PersonDAO<Student> {
... some operations unique to a student
}
The Implementations
The GenericDAO Implementation
#Repository("genericDAO")
public class GenericDAOImpl<T extends Person> implements GenericDAO<T> {
private Class<T> type;
#SuppressWarnings("unchecked")
public GenericDAOImpl() {
this.type = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), GenericDAO.class);
System.out.println(type);
}
#Resource(name = "sessionFactory")
protected SessionFactory sessionFactory;
#Transactional
#Override
public Integer save(T entity) {
return (Integer) sessionFactory.getCurrentSession().save(entity);
}
#SuppressWarnings("unchecked")
#Transactional
#Override
public T get(Integer id) {
return (T) sessionFactory.getCurrentSession().get(type, id);
}
}
The PersonDAO implementation
#Repository ("personDAO")
public class PersonDAOImpl<T extends Person> extends GenericDAOImpl<T> implements PersonDAO<T> {
.. implemented methods for person
}
The StudentDAO implementation
#Repository("studentDAO")
public class StudentDAOImpl extends PersonDAOImpl<Student> implements StudentDAO {
.. implemented methods for student
}
The POJO Classes (Hibernate Annotated)
The Person Class (Parent Abstract Class)
#MappedSuperclass
public abstract class Person {
#Id
#GeneratedValue
#Column (name = "id")
private int id;
#Column (name = "name")
private String name;
#Column (name = "age")
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The concrete class (Student)
#Entity
#Table(name = "STUDENT")
public class Student extends Person {
#Column(name = "school")
private String school;
public Student() {
}
public Student(String school) {
this.school = school;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
}
I've been thinking about how am I going to construct a design-pattern between POJOs and DAO objects for days, Until I've come up with these design based on everything I've learned from different resources around the web. I've come up with the idea of DAO and DAO implementation inheritance based on the inheritance of the POJOs.
is this a good practice? reflecting the hierarchy of the POJOs and do it in DAOs?
am I doing something wrong about here with my design? because I have a complete program that
saves and retrieves my objects from the database without any problem
I'm open to any suggestion or corrections. Thank you in advance!!!
Not a comment on the design, but... have you consider using Spring Spring Data Jpa, which allows you to:
write your repository interfaces, including custom finder methods, and Spring will provide the implementation automatically.

Resolving entities with Spring Data Neo4j returns wrong entity types

I'm experiencing some strange behavior when I'm looking up node entities with Spring Data Neo4j (SDN). If I use GraphRepository.findOne(long) it will return an entity with that identifier even though the entity is not of the same type.
This is what my (very) simplified entity structure looks like:
#NodeEntity
protected abstract class BaseEntity {
#GraphId
private Long id;
#JsonIgnore
#RelatedTo(type = RelationType.ENTITY_AUDIT)
private Audit audit;
}
#NodeEntity
public final class Person extends BaseEntity {
#Indexed(indexType = IndexType.FULLTEXT)
private String firstName;
#Indexed(indexType = IndexType.FULLTEXT)
private String lastName;
}
#NodeEntity
public class Audit extends BaseEntity {
#RelatedTo(type = RelationType.ENTITY_AUDIT, direction = Direction.INCOMING)
private BaseEntity parent;
private Long date;
private String user;
}
For every entity type, I've created repositories like this:
#Repository
public interface PersonRepository extends GraphRepository<Person> {}
#Repository
public interface AuditRepository extends GraphRepository<Audit> {}
I've got an abstract base class for my service layer classes. That is what they roughly look like:
public abstract class MyServiceImpl<T extends BaseEntity> implements MyService<T> {
private GraphRepository<T> repository;
public MyServiceImpl(final GraphRepository<T> repository) {
this.repository = repository;
}
#Override
public T read(final Long identifier) throws EntityNotFoundException {
return repository.findOne(identifier);
}
#Override
public T create(final T entity) {
return repository.save(entity);
}
}
#Service
public class PersonServiceImpl extends MyServiceImpl<Person> implements PersonService {
private PersonRepository personRepository;
#Autowired
public PersonServiceImpl(final PersonRepository personRepository) {
super(personRepository);
this.personRepository = personRepository;
}
}
When I execute the following code, the result is not as expected:
Person person = new Person();
person.setFirstName("Test");
person.setLastName("Person");
personService.create(person);
// suppose the person identifier is 1L
final Audit audit = auditRepository.findOne(1L);
You'd expect that the AuditRepository would return null, but this in not the case. Instead, it returns an Audit with identifier 1L and null in all of its properties. It seems that as long as there's a node that corresponds to a given identifier, it will be returned, no mather what its type is. If Person and Audit would have had matching property names, they would contain their values too... Is all this expected behavior, or am I missing something?
For now, I've solved this problem with the code below, where I do the type check myself.
public abstract class MyServiceImpl<T extends BaseEntity> implements MyService<T> {
private GraphRepository<T> repository;
public MyServiceImpl(final GraphRepository<T> repository) {
this.repository = repository;
}
#Override
public T read(final Long identifier) throws EntityNotFoundException {
return get(identifier);
}
protected T get(final Long identifier) throws EntityNotFoundException {
final T entity = repository.findOne(identifier);
final Class<T> type = getServiceType();
if (entity == null || !(type.equals(repository.getStoredJavaType(entity)))) {
throw new EntityNotFoundException(type, identifier);
}
return entity;
}
#SuppressWarnings("unchecked")
private Class<T> getServiceType() {
return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
}
If you need more configuration, please let me know.
My framework versions are:
<spring.version>3.2.0.RC1</spring.version>
<neo4j.version>1.8</neo4j.version>
<spring.data.neo4j.version>2.1.0.RELEASE</spring.data.neo4j.version>
we had that behavior before that it failed on the wrong entity type being returned, we changed that behavior so that the type you provide is used to automatically project the node to.
public <S extends PropertyContainer, T> T createEntityFromStoredType(S state, MappingPolicy mappingPolicy) {..}
template. createEntityFromStoredType(node, null) will get you the object with the stored state.
public Class getStoredJavaType(Object entity) {}
gives you the stored class for a node or relationship (or entity)
We had a discussion of changing the behavior back and failing esp. in Repositories.
The question is, what should happen then? An Exception? A Null result? ...
In general if you provide a raw node-id that is valid, returning an error or Null doesn't seem to be like a correct answer either?

Resources