Spring DataJPA custom query issue: - java

I have a setup with JPA (hibernate + postgresql) and MongoDB:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
My Repository Interface is:
#Repository
public interface JpaModelRepository extends JpaRepository<ModelEntity, Integer> {
public ModelEntity findByName(String modelNameSample);
}
My Entity:
#Entity
#Table (name = "model")
public class ModelEntity implements GenericId<Integer>, Serializable {
....
#Column (name = "name_tx")
private String name;
Implementation of the repository interface is auto-generated by SpringData. If I remove the findByName, all works fine in my project. If I leave it I have this in tomcat error log:
Caused by: java.lang.NoSuchMethodError: org.springframework.data.repository.query.parser.Part.getProperty()Lorg/springframework/data/repository/query/parser/Property;
at org.springframework.data.jpa.repository.query.JpaQueryCreator.toPredicate(JpaQueryCreator.java:163)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:95)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:49)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createCriteria(AbstractQueryCreator.java:109)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:73)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.<init>(PartTreeJpaQuery.java:102)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:59)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:93)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:164)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:71)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:269)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:142)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:114)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:38)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
... 85 more
Tried to use this documentation but failed for some reason:
Spring Doc
Hope is one of you guys managed to create a custom query (like findBySomeProperty(...)) ...
Thank you

The Spring data APIs changed bewteen 1.0 and 1.1 releases, that is why this error. Use the same version for both of your dependencies and it should work.

I had the same problem of
org.springframework.data.repository.query.parser.PartTree.isCountProjection()Ljava/lang/Boolean;
But I resolved it by using a proper combination of jars like
spring-data-jpa-1.2.0.RELEASE.jar <BR>
spring-data-commons-1.6.3.RELEASE.jar <BR>
spring-data-commons-core-1.4.1.RELEASE.jar<BR>
hibernate-entitymanager-4.1.12.final.jar<BR>
hibernate-jpa-2.1-api-1.0.0.final.jar<BR>
hibernate-validator-4.2.0.final.jar<BR>
hibernate-commons-annotations-4.0.0.CR2.jar<BR>
and using Spring core 3.2.5 version of jars. The problem was solved.
I was also using a proper dialect, i.e. the right driver to connect to the database.

I found the answer:
<spring.version>3.1.2.RELEASE</spring.version>
<spring-data.jpa.version>1.2.0.BUILD-SNAPSHOT</spring-data.jpa.version>
<spring-data.mongodb.version>1.1.0.BUILD-SNAPSHOT</spring-data.mongodb.version>
https://github.com/SpringSource/spring-data-multistore-test
I did some maven test combining version on that git repository

I got the same problem when trying to use Spring Data JPA + Hibernate + Spring Framework 4.0. The problem is that the Spring Data project doesn't keep-up at the same rate as the Spring Framework project.
I resolve the problem using the proper JAR version combination and excluding any other Spring project, so that those depended JAR could be downloaded correctly and automatically based on the "Spring Data" pom.xml file. Check here all the Spring Data dependencies: http://search.maven.org/#artifactdetails%7Corg.springframework.data%7Cspring-data-jpa%7C1.6.0.RELEASE%7Cjar
I changed my maven pom.xml file to:
<properties>
<!-- Generic properties -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>3.2.9.RELEASE</spring-framework.version>
<spring-data.version>1.6.0.RELEASE</spring-data.version>
<!-- Hibernate / JPA -->
<hibernate.version>3.6.10.Final</hibernate.version>
<!-- Test -->
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<!-- Spring framework -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring-data.version}</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>${hibernate-jpa.version}</version>
</dependency>
....
</dependencies>

Related

Creating and importing a custom Spring library whilst separating shared dependencies

Im looking to create a Spring library project to share across an internal team.
At a very basic concept level The library will send message events to a queue and my plan is to standardise this within a team across several Spring Boot Microservices send messages the same way.
My pom in the library project looks something like this
<artifactId>my-library</artifactId>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
etc...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
I have a service in the library project that looks like this
public class EventService {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public void sendAuditEvent(AuditMessage auditMessage){
Set<ConstraintViolation<AuditMessage>> violations = validator.validate(auditMessage);
if(!isEmpty(violations)){
log.error("Unable to send audit message");
violations.stream().forEach( v-> log.error(v.getMessage()));
}
log.info("Found {} violations", violations.size());
// etc blah blah
return;
}
}
When I import the library into another project my thinking is that I can Autowire the EventService. By adding it in the pom and then
#ComponentScan({"my.library.package.eventlibrary.service"})
How do I prevent spring version locking? If the library is using spring 2.1.5.RELEASE today and the project that imports the library uses a different version would I not end up with potentially maven conflicts?
Also lets say the project that imports the library uses a lower version of hibernate api and the library has 6.0.16.Final. How would I prevent the project from using the newer one found one in the library classpath?
To clarify my question further is there a way I can separate the dependencies in the library from the project that uses it.
Pre Java 9. You can exclude the spring dependencies using maven when you declare the dependency to your module, same goes on for Hibernate. But you can't tell to your module to use a different hibernate version in a WAR.
If you want to work around this you can develop your library as independent micro service expose interface in the form of REST or Websocket if you want full duplex communication or something else JMS whatever....
Post Java 9 you can use java modularity to define the exact dependencies for your jar module. Check Project Jigsaw https://www.baeldung.com/project-jigsaw-java-modularity.
In your case in order to have different versions of the same library (hibernate). You would need two separate class loaders. To achieve this you would need to use layering read here http://openjdk.java.net/projects/jigsaw/spec/sotms/#layers
And here is the source code of many examples including ones that use layers. Focus on them : https://github.com/accso/java9-jigsaw-examples/tree/master/jigsaw-examples
You can try to exclude all transitive dependencies that your library can bring to projects that will use it.
To do this you should replace spring-boot-starter-parent with spring-boot-dependencies in dependencyManagement section and use provided scope for all dependencies which the library needs to work with and which will be exactly used by the projects, that will work with the library.
For example, a pom.xml of your library can be looks like this:
<!-- ... -->
<groupId>com.example</groupId>
<artifactId>library</artifactId>
<version>0.1.0</version>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<spring-boot.version>2.1.5.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- ... -->
Then you will be able to use your library in the different projects, that use for example the old Spring Boot:
<!-- ... -->
<groupId>com.example</groupId>
<artifactId>old-project</artifactId>
<version>0.13.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.19.RELEASE</version>
<relativePath/>
</parent>
<!-- ... -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>library</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- ... -->
So this project will use hibernate-validator:5.3.6.Final from its spring-boot-starter-web.
Important notes - the code of your library should be 'compatible' with this version of Spring Boot. In other words, you should test your library with different versions of Spring Boot in which you are interested.
See my project as an example.
Might be not what you are looking for, but you can distribute your library as a spring-boot-starter auto configuration module (of course, if the clients are spring boot applications).
This way you can control your dependencies in an agile way and you give your clients more freedom in using the library.
In your particular case, if you need to send a message to a queue you for sure need to have a corresponding classes in classpath. With auto configuration you can have Class Conditions or Been Conditions based on which you can track if your clients have correct configurations in runtime. You can also fail the context loading if something is wrong (providing a meaningful error message).
Spring also provides tracking mechanisms of what could happen if a particular class/library is missing.

Spring - Hibernate Integration

I am trying to integrate Spring 4 with Hibernate 4 and i am using eclipse ide with out maven dependencies,But i am getting below mentioned error:
Caused by: java.lang.classnotfoundexception : org.hibernate.annotations.Entity
if any one has implemented already and working fine, So please can you share the project for reference so that i can understand the flow of integration, As i am new to spring and hibernate.I need some good guidance.
you need to use some dependency, which you can find below :
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.5-Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.2.9.Final</version>
</dependency>
and if you are not using maven project then you need to download the hibernate-entitymanager and hibernate-annotations jar and add into build path and rebuild the project

I am confused with maven dependencies: "org.eclipse.persistence.jpa" and "org.hibernate"

I have a Spring MVC project using Maven.
I am using Spring-data-jpa as one of my dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.10.5.RELEASE</version>
</dependency>
Spring-data-jpa provides the api.
Therefore, I need to add another dependency which implements jpa. However, I am confused about:
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.4</version>
</dependency>
and
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.2.2.Final</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.4</version>
</dependency>
What is eclipse.persistence? And the difference with hibernate?
Please help!
Eclipse Persistence (EclipseLink) and Hibernate are both implementations of Java Persistence API, each with their own extra features and often their own bugs. In terms of speed, they're very similar to each-other, compared to the other implementations.
Only one of is used in each persistence unit, defined in META-INF/persistence.xml. Look at yours, inside the persistence-unit->provider node you will find the class that is used.
If it starts with org.hibernate, then you can safely remove the eclipse dependency.
If it starts with org.eclipse, you can remove the hibernate dependency.
If you have multiple persistence units, each one can use a different implementation/provider.

Issues with Hibernate Validator after upgrading from Hibernate 3 to 4 with Spring 4

Issues with Hibernate Validator after upgrading from Hibernate 3 to 4 with Spring 4
I took over a very old Java project (rich client, swing, hibernate 3) which has some sort of homegrown Dependency Injection, uses Hibernate 3 and it has manual transaction management. Meaning every freakin DAO method gets a boolean that triggers a session to be opened or not. You can imagine what this means when you touch that fragile construct on many places... Anyhow, I am not here to whine...here's my Problem:
I have to implement a new complex feature and soon had to realize that this whole manual transaction thing gets out of control and I could convince the customer to refactor the whole thing to use Spring transaction mgmt in combination with hibernate 4.
So I started to implement this and after some major issues I came accross, the whole thing now runs but with some more detailed hickups.
One that drives me nuts is Hibernate Validator. The existing implementation is the old fashioned way I guess. All Entity Classes derive from a class named DomainObject which contains a org.hibernate.validator.ClassValidator for all Entities that are existing in the project.
In the entities themselves this validator will be called with .InvalidValues() to verify the fields.
Since I upgraded to Hibernate-Core 4.3.6.Final with Spring 4.2.4.RELEASE I get a lot of issues when Entities are to be validated. I know I am using an old Validator Version but when I upgrade to a higher one, the whole project has countless errors like The type org.hibernate.validator.InvalidValue cannot be resolved. It is indirectly referenced from required .class files but I wasn't able to resolve this with all answers I found on SO for it.
Right now the validation which causes errors runs in a SwingWorker Thread and while debugging it I can see the exception is swallowed somewhere deep in Spring and I don't even get a stacktrace :-(
I assume the issues still comes from a bad combination of the hibernate dependencies but I was really desperate until I got something that work together which
you can see in the pom.xml snippet below.
Here the snippets
<!-- Hibernate Stuff -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.6-Final</version>
<!-- Hibernate Core needs a higher version so we exclude this one -->
<exclusions>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>3.2.0.Final</version>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.2.Final</version>
</dependency>
<!-- <dependency> -->
<!-- <groupId>org.hibernate</groupId> -->
<!-- <artifactId>hibernate-c3p0</artifactId> -->
<!-- <version>3.6.10.Final</version> -->
<!-- </dependency> -->
<!-- <dependency> -->
<!-- <groupId>javassist</groupId> -->
<!-- <artifactId>javassist</artifactId> -->
<!-- <version>3.12.0.GA</version> -->
<!-- </dependency> -->
<!-- <dependency> -->
<!-- <groupId>c3p0</groupId> -->
<!-- <artifactId>c3p0</artifactId> -->
<!-- <version>0.9.1.2</version> -->
<!-- </dependency> -->
This is the method in all Entities that will be called during validation.
/**
* validate the entity. This method will be called internally before save or
* update to check validity before sql statements
*/
#Override
#Transient
protected InvalidValue[] validate(final String fieldName) {
if (fieldName == null) {
return VALIDATOR_ASSEMBLY_ENTRY.getInvalidValues(this);
} else {
return VALIDATOR_ASSEMBLY_ENTRY.getInvalidValues(this, fieldName);
}
}
Any hints ? If you need more Code, tell me. The whole Spring and Hibernate config is done in Java. No xml.
I fix this with a little workaround. Put this in your pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-legacy</artifactId>
<version>4.0.2.GA</version>
</dependency>

java.lang.ClassNotFoundException: javax.persistence.Persistence cannot be found with JPA

I'm praticing with JPA API. I got an error
java.lang.ClassNotFoundException: javax.persistence.Persistence cannot be found
My code below:
EntityManagerFactory emf;
emf = Persistence.createEntityManagerFactory("mail");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("SELECT v FROM Version v");
List<Version> versions = query.getResultList();
The error at line emf = Persistence.createEntityManagerFactory("mail");
Any solution?
You are trying to set up a standalone JPA project. In order to do so you need a JPA provider jars. The two more popular providers are Eclipselink and Hibernate. If you are using maven you can add dependencies to their implementations.
For Eclipselink
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.1</version>
</dependency>
For Hibernate
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.6.Final</version>
</dependency>
If you are not using maven you can download their implementations from their sites and put it in your classpath.
For Eclipselink: http://www.eclipse.org/eclipselink/downloads/
For Hibernate: http://hibernate.org/orm/
Some JPA quickstarts are recommending to add only the JPA API (interface declarations only) dependencies with maven.
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
</dependency>
or
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
This approach will be successful only in server environment as the server will provide appropriate implementation at runtime.
Right Click on Project -> Properties -> Search "Deployment Assembly" -> Add Maven Dependencies.
if using maven , add below dependency in Pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
then clean install maven

Categories

Resources