I am trying to get JPA validation to work, however it seems that the validation annotations are ignored. I found this example of JPA validation on SO: JPA Entity Validation, but it does not work for me. The #NotNull and #Size annotations seem to be ignored.
As in the answer mentioned above I use only two classes:
Customer.java:
package com.validation.test;
import javax.persistence.*;
import javax.validation.constraints.*;
#Entity
#Table(name = "T_CUSTOMER")
public class Customer {
#Id
#NotNull
#SequenceGenerator(name = "customerIdSeq", sequenceName = "T_CUSTOMER_ID_SEQ", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customerIdSeq")
private Long id;
#NotNull
#Size(min = 3, max = 80)
private String name;
public Customer() {};
public Customer(String name) {
this.name = name;
}
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;
}
}
CustomerTest.java:
package com.validation.test.test;
import static org.junit.Assert.*;
import javax.persistence.*;
import javax.validation.*;
import javax.validation.constraints.Size;
import org.junit.*;
import com.validation.test.Customer;
public class CustomerTest {
private static EntityManagerFactory emf;
private EntityManager em;
#BeforeClass
public static void createEntityManagerFactory() {
emf = Persistence.createEntityManagerFactory("testPU");
}
#AfterClass
public static void closeEntityManagerFactory() {
emf.close();
}
#Before
public void beginTransaction() {
em = emf.createEntityManager();
em.getTransaction().begin();
}
#After
public void rollbackTransaction() {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em.isOpen()) {
em.close();
}
}
#Test
public void nameTooShort() {
try {
Customer customer = new Customer("bo");
em.persist(customer);
em.flush();
fail("Expected ConstraintViolationException wasn't thrown.");
} catch (ConstraintViolationException e) {
assertEquals(1, e.getConstraintViolations().size());
ConstraintViolation<?> violation = e.getConstraintViolations().iterator().next();
assertEquals("name", violation.getPropertyPath().toString());
assertEquals(Size.class, violation.getConstraintDescriptor().getAnnotation().annotationType());
}
}
}
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.validation.test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<repositories>
<repository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc5</artifactId>
<version>11.2.0.2.0</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.3.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>wwd-bs</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.validation.test.Customer</class>
<properties>
<property name="eclipselink.logging.level" value="FINE" />
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:#localhost:1521:orcl" />
<property name="javax.persistence.jdbc.user" value="user" />
<property name="javax.persistence.jdbc.password" value="password" />
<property name="eclipselink.logging.level" value="INFO" />
</properties>
</persistence-unit>
</persistence>
The test fails at the fail(...) so the exception is never thrown.
How can I make (any) validation work with JPA? I cannot use Hibernate or Spring.
Thank you for your help
EDIT: added hibernate-validator to pom.xml (with no effect)
Add this to your pom.xmls.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
<exclusions>
<exclusion>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
And set validation property to AUTO this must to be enable in persistence.xml
<property name="javax.persistence.validation.mode" value="AUTO" />
Or do it progrmatically.
final Set<ConstraintViolation<Object>> errors = validator.validate(object, classes);
Do you have a runtime implementation of the validator on your classpath? Typically people seem to use hibernate validator. (e.g. indeed by adding hibernate-validator to your pom.xml)
edit: Your version of EclipseLink also looks quite old, it should be a JPA2 implementation. If it is a JPA1 implementation, you should register your own event listener, which will be a bit more work. You can find some hints in the eclipse docs (scroll down to JPA section), but it looks like you'll have to slightly edit the standard validators to make it work. This blog might be helpful.
Related
I am newbie coder and I am trying to create a Spring boot API using MongoDB. This is the schema template of the database.
{
"id":"string",
"user_name":"string"
"product":[
{
"product_id":"string",
"prod_name":"string",
"price":"double",
"quantity":"number",
}],
"total":"double"
}
This is my entity class User.java
#Getter
#Setter
#NoArgsConstructor
#Document(collection="user")
public class User {
#Id
private String id;
#Indexed(unique=true)
private String user_name;
private Product product;
private double total;
}
This is another entity class Product.java
#Getter
#Setter
#Document(collection="product")
public class Product {
#Id
private String prod_id;
#Indexed(unique=true)
private String prod_name;
private double price;
private int quantity;
}
This is my UserRepository.java interface
#Repository
public interface UserRepository extends MongoRepository<User,String> {
}
This is my UserService.java interface
public interface UserService {
void saveUser(User user);
}
This is my UserServiceImpl.java class
#Service
public class UserServiceImpl implements UserService {
#Autowired
UserRepository userRepo;
#Override
public void saveUser(User user) {
userRepo.save(user);
}
}
This is my UserController.java class
#RestController
#RequestMapping("/usercart")
public class UserController {
#Autowired
private UserService userService;
#Autowired
private UserRepository userRepository;
#GetMapping("/")
public List<User> getCartInfo()
{
return userRepository.findAll();
}
#PostMapping("/order")
public ResponseEntity<?> add(#RequestBody User user)
{
userService.saveUser(user);
return new ResponseEntity<>(HttpStatus.OK);
}
}
This is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>cartDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cartDemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
This is my application.properties file
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=UserCart
When I try to use post method like
Body -
{ "id":"1222",
"user_name":"shivam",
"product":[{
"prod_id":"w121", "prod_name":"wheel",
"price":10,
"quantity":1 }],
"total":10 }.
My MongoDB object looks like - _id:ObjectId("e6789")
total :0, _class:"com.trial.spring.api.user.User"
I don't see your property file here, but most likely you are missing below properties in your application.properties file:
spring.data.mongodb.uri=mongodb://<username>:<pwd>#<host>/datatbase_name
I am trying to configure simple database using Spring JPA, and I encountered, which seems simular to some questions here, but solution to this aren`t working.
I am trying to insert following POJO into PostgreSQL database :
#Entity
#Table(name = "students", schema = "public")
public class Student {
#Id
#Column(name = "ID")
private UUID id = UUID.randomUUID();
#Column(name = "First_Name")
private String firstName;
#Column(name = "Last_Name")
private String lastName;
#Column(name = "Age")
private Integer age;
#Column(name = "Passport_Number")
private Integer passNumber;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "Group_ID", referencedColumnName = "ID")
private Group group;
public UUID getId() {
return id;
}
public void setId(#NonNull UUID id) { this.id = id; }
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getPassNumber() {
return passNumber;
}
public void setPassNumber(Integer passNumber) {
this.passNumber = passNumber;
}
public Group getGroup() { return group; }
public void setGroup(Group group) { this.group = group; }
public void setUpdate(#NonNull Student student) {
setFirstName(student.getFirstName());
setLastName(student.getLastName());
setAge(student.getAge());
setPassNumber(student.getPassNumber());
}
}
Table of my database is created using following sql :
CREATE TABLE students (
"ID" UUID,
"First_Name" VARCHAR(50),
"Last_Name" VARCHAR(50),
"Age" INT,
"Passport_Number" INT,
"Group_ID" UUID,
UNIQUE("First_Name", "Last_Name"),
UNIQUE("Passport_Number"),
FOREIGN KEY("Group_ID") REFERENCES groups("ID"),
PRIMARY KEY ("ID")
);
When trying to insert new Student, Hibernate builds following sql (message in console) :
Hibernate:
select
student0_.ID as id1_0_0_,
student0_.Age as age2_0_0_,
student0_.First_Name as first_na3_0_0_,
student0_.Group_ID as group_id6_0_0_,
student0_.Last_Name as last_nam4_0_0_,
student0_.Passport_Number as passport5_0_0_
from
public.students student0_
where
student0_.ID=?
And here is the problem. There is no student0_, and so psql off course gives org.postgresql.util.PSQLException: ERROR: column student0_.id does not exist
I tryied also to give name variable to #Entity specifically, but to no effect. Also I tried to change naming stratagies : implicit naming strategy, improved naming strategy, physical naming strategy, implicit legacy naming strategy. And I already tried to change dialect, but also nothing.
My current hibernate properties are :
#Hibernate
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto = none
hibernate.ejb.naming_strategy = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Also this is Configuration that I use :
#Configuration
#EnableTransactionManagement
#PropertySource({"classpath:dao.properties"})
#EnableJpaRepositories(basePackages = {"com.university.dao"})
public class ApplicationConfig {
#Autowired
private Environment environment;
public ApplicationConfig() {
super();
}
#Bean
public DataSource dataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(environment.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(environment.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(environment.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(environment.getProperty("jdbc.password")));
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
Environment environment) {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactory.setJpaProperties(getHibernateProperties());
entityManagerFactory.setPackagesToScan("com.university.domain");
return entityManagerFactory;
}
#Bean
public PlatformTransactionManager transactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory(dataSource(),environment).getObject());
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
final Properties getHibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", environment.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", environment.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", environment.getProperty("hibernate.show_sql"));
hibernateProperties.setProperty("hibernate.format_sql", environment.getProperty("hibernate.format_sql"));
hibernateProperties.setProperty("hibernate.ejb.naming_strategy", environment.getProperty("hibernate.ejb.naming_strategy"));
return hibernateProperties;
}
}
As for versions, I am using Spring JPA 2.3.1.Release and Hibernate 5+, here is full maven pom file :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.3.1.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>university</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.reporting.outputEncoding>UTF-8</project.build.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit-jupiter.version>5.6.1</junit-jupiter.version>
<junit.version>4.13</junit.version>
<org.springframework.version>5.2.7.RELEASE</org.springframework.version>
<org.springframework.boot.version>2.3.1.RELEASE</org.springframework.boot.version>
<org.hibernate.validator.version>6.1.5.Final</org.hibernate.validator.version>
<org.apache.tomcat.version>9.0.36</org.apache.tomcat.version>
<com.vaadin.version>16.0.0</com.vaadin.version>
<org.junit.jupiter.version>5.6.2</org.junit.jupiter.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.university.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${org.springframework.boot.version}</version>
</plugin>
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<version>${com.vaadin.version}</version>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>${com.vaadin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${org.springframework.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>${org.springframework.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${org.springframework.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${org.springframework.boot.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${org.hibernate.validator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>${org.apache.tomcat.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
<version>${com.vaadin.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin</artifactId>
<version>${com.vaadin.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.12.jre7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${org.junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${org.junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${org.junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.19.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-reflect</artifactId>
<version>2.0.7</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
How may I remove this error without explicitly(manually) rewriting hibernate queries in configuration (so hibernate would use correct column/table names automatically)?
Regardless if your answer/comment helps or not, thank you very much for your effort:)
There is a student0_, it's the table alias declared in from student student0_. It's the column that's not being found since it wasn't escaped properly, so student0_.ID really is treated as student0_.id.
Using case sensitive names isn't recommended in Postgres, whereas it's common with other databases. So instead of "First_name", just use first_name. Otherwise you need to escape the names everywhere e.g.
#Column(name = "\"First_Name\"")
and that's not pretty, and all other Postgres users will frown upon your database schema.
I have a table with a composite primary key - groupId and batchId. Entity class looks like:
#Entity(name="EMPLOYEE")
public class Employee {
#EmbeddedId
private EmployeePK employeePK;
//Other columns and their getters and setters
//Getters and setters
}
Composite PK:
#Embeddable
public class EmployeePK implements Serializable {
private long groupId;
private long batchId;
#GeneratedValue(strategy=GenerationType.AUTO)
public long getBatchId() {
return batchId;
}
public void setBatchId(long batchId) {
this.batchId = batchId;
}
}
I'm trying to auto increment the batch Id, for a new record to be inserted.
//For saving
Employee employee = new Employee();
EmployeePK pk = new IRAmendmentBatchesPK();
pk.setBatchId(0);
pk.setGroupId(4388);
Employee employee = employeeRepository.save(employee);
//Repository Interface
public interface EmployeeRepository extends JpaRepository<Employee, EmployeePK>{
}
I'm explicity setting batchId as 0, in hopes that the auto-incremented value is set in the batchId during save(insert). As of now, this code will save a new entry with batchId as 0.
As I have mentioned in comment, I have used #IdClass it worked while I have tried in hsqldb in-memory database, but failed to work in mysql.
Please note I am using hibernate 5
You may give a try with oracle, I couldn't recollect but it should work. But please check for if any drawbacks with the approach if any.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.techdisqus</groupId>
<artifactId>spring5-mvc-hibernate-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
<spring.version>5.0.0.RELEASE</spring.version>
<hibernate.version>5.2.11.Final</hibernate.version>
<hibernate.validator>5.4.1.Final</hibernate.validator>
<c3p0.version>0.9.5.2</c3p0.version>
<jstl.version>1.2.1</jstl.version>
<tld.version>1.1.2</tld.version>
<servlets.version>3.1.0</servlets.version>
<jsp.version>2.3.1</jsp.version>
<hsqldb.version>1.8.0.10</hsqldb.version>
</properties>
<dependencies>
<!-- Spring MVC Dependency -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring ORM -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Hibernate ORM -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Hibernate-C3P0 Integration -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- Hibernate Validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator}</version>
</dependency>
<!-- JSTL Dependency -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>${tld.version}</version>
</dependency>
<!-- Servlet Dependency -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlets.version}</version>
<scope>provided</scope>
</dependency>
<!-- JSP Dependency -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>${jsp.version}</version>
<scope>provided</scope>
</dependency>
<!-- HSQL Dependency -->
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- Embedded Apache Tomcat required for testing war -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
Book.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
#Entity(name = "Book")
#Table(name = "book")
#IdClass( PK.class )
public class Book {
#Id
#Column(name = "registration_number")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long registrationNumber;
#Id
#Column(name = "publisher_id")
private Integer publisherId;
private String title;
public Long getRegistrationNumber() {
return registrationNumber;
}
public void setRegistrationNumber(Long registrationNumber) {
this.registrationNumber = registrationNumber;
}
public Integer getPublisherId() {
return publisherId;
}
public void setPublisherId(Integer publisherId) {
this.publisherId = publisherId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Override
public String toString() {
return "Book [registrationNumber=" + registrationNumber + ", publisherId=" + publisherId + ", title=" + title
+ "]";
}
}
PK.java
import java.io.Serializable;
import java.util.Objects;
public class PK implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2371758145387850080L;
private Long registrationNumber;
private Integer publisherId;
public PK(Long registrationNumber, Integer publisherId) {
this.registrationNumber = registrationNumber;
this.publisherId = publisherId;
}
public PK() {
}
#Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
PK pk = (PK) o;
return Objects.equals( registrationNumber, pk.registrationNumber ) &&
Objects.equals( publisherId, pk.publisherId );
}
#Override
public int hashCode() {
return Objects.hash( registrationNumber, publisherId );
}
}
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.archive.autodetection">class,hbm</property>
<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.connection.url">jdbc:hsqldb:mem:test</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.acquire_increment">2</property>
<property name="hibernate.c3p0.acquire_increment">1800</property>
<property name="hibernate.c3p0.max_statements">150</property>
</session-factory>
</hibernate-configuration>
HibernateConfig.java
#Configuration
#EnableTransactionManagement
#ComponentScans(value = { #ComponentScan("com.techdisqus")})
public class HibernateConfig {
#Autowired
private ApplicationContext context;
#Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setConfigLocation(context.getResource("classpath:hibernate.cfg.xml"));
factoryBean.setAnnotatedClasses(Book.class);
return factoryBean;
}
#Bean
public HibernateTransactionManager getTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(getSessionFactory().getObject());
return transactionManager;
}
}
BookDAOImpl.java
#Repository
public class BookDAOImpl implements BookDAO {
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(Book book) {
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.persist(book);
tx.commit();
session.close();
}
}
client code:
public class SpringHibernateMain2 {
public static void main(String[] args) {
ApplicationContext appContext = new AnnotationConfigApplicationContext(HibernateConfig.class);
BookDAO personDAO = appContext.getBean(BookDAO.class);
Book book = new Book();
book.setPublisherId(12);
book.setTitle("t 1");
//book.setRegistrationNumber(2l);
personDAO.save(book);
System.out.println("book::"+book);
//context.close();
}
}
from logs while using with H:
Hibernate: call next value for hibernate_sequence Hibernate: insert
into book (title, publisher_id, registration_number) values (?, ?, ?)
book::Book [registrationNumber=1, publisherId=12, title=t 1]
The below is the error I get while I try with MySql
Hibernate: select next_val as id_val from hibernate_sequence for
update Dec 04, 2018 6:24:53 PM
org.hibernate.id.enhanced.TableStructure$1$1 execute ERROR: could not
read a hi value java.sql.SQLSyntaxErrorException: Table
'security.hibernate_sequence' doesn't exist
I have tried with accepted answer in the post
Hibernate insert failing when embedded key contains identity column on SQL Server
but no luck with it.
#Embeddable
public class EmployeePK implements Serializable {
private long groupId;
#GeneratedValue(strategy = GenerationType.AUTO)
private long batchId;
public long getBatchId() {
return batchId;
}
public void setBatchId(long batchId) {
this.batchId = batchId;
}
//implements equals and hashcode
}
It's precised in the Javadoc of oracle that is not possible and not in the spec : https://docs.oracle.com/javaee/6/api/javax/persistence/GeneratedValue.html
Use of the GeneratedValue annotation is not supported for derived primary keys.
And I found nothing about how to do it with build in tools. So you need to do yours own implementation of that.
This is my first program on REST API using jersey. My rest API is giving me an Error code 500 when I try to get the response back in XML but it is working fine for JSON.
Can someone tell me what I am doing wrong?
There is no error shown in the console.
public class MyResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("/cust")
public Customer getCust() {
Customer cus= new Customer();
cus.setName("john");
cus.setId(1);
cus.setAddress("india");
return cus;
}
#GET
#Path("/test/order")
#Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Order getOrder() {
List<Order> o =new ArrayList<Order>();
Order ord=new Order();
ord.setCost(0);
ord.setProductID(0);
ord.setQuantity(0);
ord.setShippingAddress("abcd");
o.add(ord);
return ord;
}
}
My customer class
package in.octalian.mobileservice.model;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Customer {
private int id;
private String name ;
private String address;
public Customer() {}
public Customer(int id,String name,String address) {
this.id=id;
this.name=name;
this.address=address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>in.octalian</groupId>
<artifactId>mobileservice</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mobileservice</name>
<build>
<finalName>mobileservice</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<!-- uncomment this to get JSON support -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.27</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
XML response that I attach to give more information to you.
The issue is that you are trying to access a URI /cus but your code have a declaration as #Path("/cust"). So you should be using /cust.
Secondly, you could run your server(apache-tomcat for me) in debug mode to get debugging information if no logs are getting logged in the console for some error
Also, you need to add the header "Accept" in the request with the expected result format type. If not specified the first one will be considered as it appears first.
Utilising the Java JPA with Eclipse Link I am attempting to persist a simple Post model of a Blog application into a MySQL database however I am recieving the error No Persistence provider for EntityManager named
Here is the code I am utilising
Exception Text
javax.persistence.PersistenceException: No Persistence provider for
EntityManager named blog
javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
com.uk.jacob.blog.controllers.PostController.(PostController.java:9)
com.uk.jacob.blog.controllers.HomeController.doGet(HomeController.java:51)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
App Structure
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.uk.jacob</groupId>
<artifactId>blog</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Jacob Clark Blog</name>
<description>A blog for jacob.uk.com</description>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.0-M3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.33</version>
</dependency>
</dependencies>
</project>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="blog" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>uk.com.jacob.blog.models.Post</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://localhost:3306/jpadb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
Post Bean
package com.uk.jacob.blog.models;
import java.util.Date;
import javax.persistence.*;
#Entity
public class Post {
#Id
private int _id;
private String _title;
private String _author;
private String _body;
private Date _published;
public int getId(){
return _id;
}
public void setId(int _id){
this._id = _id;
}
public String getTitle() {
return _title;
}
public void setTitle(String _title) {
this._title = _title;
}
public String getAuthor() {
return _author;
}
public void setAuthor(String _author) {
this._author = _author;
}
public String getBody() {
return _body;
}
public void setBody(String _body) {
this._body = _body;
}
public Date getPublished() {
return _published;
}
public void setPublished(Date _published) {
this._published = _published;
}
}
Post Controller
package com.uk.jacob.blog.controllers;
import javax.persistence.*;
import com.uk.jacob.blog.models.Post;
public class PostController {
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("blog");
private EntityManager em = emf.createEntityManager();
private EntityTransaction tx = em.getTransaction();
public Post createPost(Post post){
tx.begin();
em.persist(post);
tx.commit();
return post;
}
public Post getPost(int id){
return em.find(Post.class, id);
}
public void removePost(Post post){
em.remove(em.merge(post));
}
public void updatePost(Post post){
tx.begin();
Post postToBeUpdated = em.merge(post);
tx.commit();
}
}
It's because of you don't have eclipselink dependency in your pom.xml. Also
You don't need
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.0-M3</version>
</dependency>
just
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.4.2</version>
</dependency>
is enough (version may change)