#query annotation doesn't work with hibernate-ogm and mongodb in spring boot - mongodb

I wrote a Spring boot,hibernate orm application using mysql database.... But now I want to switch to mongodb... I used Hibernate-ogm for fulfill my requirement. When run the application the console shows successfully switch to mongodb using hibernate-ogm... But the query is not working... I import below packages for my repository to hibernate-orm and these imports works fine with mysql... But in hibernate-ogm #query annotation doesn't work...
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.jpa.repository.Query;
This is my model
#Entity
#Indexed
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String nic;
private String emp;
private String firstName;
private String lastName;
#NotEmpty
private String mobile;
private String email;
private String status;
private String agency;
#NotEmpty
#Column(unique = true)
private String userName;
#NotEmpty
private String password;
private String userIDandTime;
private String recentUpdateBy;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "user_roles",
joinColumns = {
#JoinColumn(name = "id")},
inverseJoinColumns = {
#JoinColumn(name = "roleId")})
private Set<Role> userRoles;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "user_units",
joinColumns = {
#JoinColumn(name = "id")},
inverseJoinColumns = {
#JoinColumn(name = "unitId")})
private Set<Unit> userUnits;
}
This is my full repository
package lk.tradeportal.repository;
import lk.tradeportal.domain.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
/**
* Created by Ignotus on 1/28/2017.
*/
public interface UserRepository extends CrudRepository<User, Long> {
#Override
User save(User user);
#Override
User findOne(Long id);
#Query("select u from User u where u.userName!='super#allSLSI'")
List<User> findAll();
#Query("select u from User u where u.agency = :agency and u.firstName !='admin'")
List<User> findAllStaffUsersByOGA(#Param("agency") String agency);
#Query("select u from User u where u.nic='N/A' and u.firstName='N/A' and u.email='N/A'")
List<User> profileNotCompletedUsers();
#Query("select u from User u where u.agency!='SLSI'")
List<User> chafindAll();
#Query("select u from User u where u.userName = :userName")
User getUserByLoginUserName(#Param("userName") String userName);
#Query("select u from User u where u.id = :userId")
User getUserByUserId(#Param("userId") Long userId);
#Query("select u.email from User u where u.agency !='SLSI'")
List<User> getEmails();
#Query("select a from User a where a.nic = :nic")
User getAgentByNIC(#Param("nic") String nic);
#Override
void delete(Long id);
#Override
void delete(User user);
}
This is my Service class
package lk.tradeportal.services;
import java.text.SimpleDateFormat;
import java.util.Date;
import lk.tradeportal.domain.Role;
import lk.tradeportal.domain.User;
import lk.tradeportal.repository.RoleRepository;
import lk.tradeportal.repository.UserRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import lk.tradeportal.domain.Unit;
import lk.tradeportal.repository.UnitRepository;
import lk.tradeportal.security.domain.AuthenticatedUser;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Created by ignotus on 1/31/2017.
*/
#Service
public class UserServices {
private static final Logger serviceLogger = LogManager.getLogger(UserServices.class);
#Autowired
private UserRepository userRepository;
#Autowired
private RoleRepository roleRepository;
#Autowired
private UnitRepository unitRepository;
#Autowired
private UserServices UserService;
public User getUserFromUserId(Long id) {
return userRepository.getUserByUserId(id);
}
public List<User> getAllUsers() {
Runtime.getRuntime().gc();
return userRepository.findAll();
}
public User getUserByLoginUserName(String userName) {
return userRepository.getUserByLoginUserName(userName);
}
public List<User> findAllStaffUsersByOGA(String agency) {
return userRepository.findAllStaffUsersByOGA(agency);
}
public List<User> profileNotCompletedUsers() {
return userRepository.profileNotCompletedUsers();
}
public List<User> getChaAllUsers() {
System.out.println(userRepository.chafindAll());
return userRepository.chafindAll();
}
public List<Role> getAllRoles() {
return roleRepository.findAll();
}
public List<Role> findTraderRoles() {
return roleRepository.findTraderRoles();
}
public List<Role> findMOIC() {
return roleRepository.findMOIC();
}
public List<Role> SuperADMINRoles() {
return roleRepository.SuperADMINRoles();
}
public List<Unit> getAllUnits() {
return unitRepository.findAll();
}
public void deleteUserById(String id) {
User user = userRepository.findOne(Long.valueOf(id));
userRepository.delete(user);
}
public User getAgentByNIC(String nic) {
return userRepository.getAgentByNIC(nic);
}
}
This is my application config.
package lk.tradeportal;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import javax.annotation.PreDestroy;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Created by ignotus on 1/22/2017.
*/
#Configuration
#ComponentScan(basePackages = "lk.tradeportal")
#EnableWebMvc
#ImportResource(locations = "classpath:tradeportal-servlet-config.xml")
#EnableJpaRepositories(basePackages="lk.tradeportal.repository")
#EnableTransactionManagement
public class TRADEPORTALStarter extends SpringBootServletInitializer {
private static final Logger slsiLogger = LogManager.getLogger(TRADEPORTALStarter.class);
private static ConfigurableApplicationContext context;
public static void main(String[] args) {
slsiLogger.info("Starting application");
SpringApplication application = new SpringApplication(TRADEPORTALStarter.class);
context = application.run(args);
application.setRegisterShutdownHook(true);
}
#PreDestroy
private static void closeAppContext(){
context.close();
}
#Override
protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(TRADEPORTALStarter.class);
}
}
This is my persistence.xml
<?xml version="1.0"?>
<persistence 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"
version="2.0">
<persistence-unit name="ogm-jpa-tutorial" transaction-type="RESOURCE_LOCAL">
<!-- Use Hibernate OGM provider: configuration will be transparent -->
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<class>lk.tradeportal</class>
<properties>
<property name="hibernate.ogm.datastore.provider" value="mongodb" />
<!--<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform" />-->
<property name="hibernate.ogm.datastore.create_database" value="true"/>
<property name="hibernate.ogm.datastore.database" value="trade_portal_db"/>
</properties>
</persistence-unit>
</persistence>
My dependencies are
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<!--handle servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!--<Email Dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>1.4.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.1</version>
</dependency>
<!--jasper-->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>3.7.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.5.5</version>
<type>jar</type>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web-services -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.ws.security/wss4j -->
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
<version>1.6.19</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-libs -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-libs</artifactId>
<version>1.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
<version>2.2.0.RELEASE</version>
<type>jar</type>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
<groupId>org.hibernate.ogm</groupId>
<artifactId>hibernate-ogm-mongodb</artifactId>
<version>5.1.0.Final</version>
<exclusions>
<exclusion>
<groupId>org.hibernate.hql</groupId>
<artifactId>hibernate-hql-parser</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.4.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.ogm/hibernate-ogm-core -->
<dependency>
<groupId>org.hibernate.ogm</groupId>
<artifactId>hibernate-ogm-core</artifactId>
<version>5.1.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-search-orm -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>5.6.1.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-search-engine -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-engine</artifactId>
<version>5.6.1.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.1.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.hql</groupId>
<artifactId>hibernate-hql-parser</artifactId>
<version>1.4.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
</dependencies>
What is the error in #query annotation. How I get I data from my database.. Please help me.

Related

Postgresql jsonb doesn't work with Spring Data JPA

I tried to save into a jsonb column but I didn't find any solution of my problem.
Postgresql 15.
This is the mapping class
#Getter
#Setter
#NoArgsConstructor
#Entity(name = "template")
#Table(name = "template")
public class Template {
#Id
#Column(name = "ID")
private UUID id;
#Column(name = "name")
private String name;
#Column(name = "version")
private Integer version;
#Convert(converter = TemplateFullConverter.class)
#Column(name = "tbody")
private TemplateFull tbody;
}
With the following TemplateFullConverter class
#Converter
public class TemplateFullConverter implements AttributeConverter<TemplateFull, PGobject> {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public PGobject convertToDatabaseColumn(TemplateFull templateFull) {
final PGobject po = new PGobject();
po.setType("jsonb");
try {
po.setValue(JsonHelper.fromModelToString(templateFull));
} catch (SQLException | JsonProcessingException e) {
logger.error("Cannot convert TemplateFull to PGobject");
throw new RuntimeException(e);
}
return po;
}
#Override
public TemplateFull convertToEntityAttribute(PGobject pGobject) {
if (pGobject == null || pGobject.getValue() == null) {
return null;
}
try {
return JsonHelper.fromStringToModel(pGobject.getValue(), TemplateFull.class);
} catch (IOException e) {
logger.error("Cannot convert PGobject to TemplateFull");
throw new RuntimeException(e);
}
}
}
This is the pom:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.2</version>
</dependency>
During the save, there is the following error:
org.postgresql.util.PSQLException: ERROR: column "tbody" is of type jsonb but expression is of type bytea
Hint: You will need to rewrite or cast the expression.
Position: 117
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2676) ~[postgresql-42.5.3.jar:42.5.3]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2366) ~[postgresql-42.5.3.jar:42.5.3]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:356) ~[postgresql-42.5.3.jar:42.5.3]
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:496) ~[postgresql-42.5.3.jar:42.5.3]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:413) ~[postgresql-42.5.3.jar:42.5.3]
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190) ~[postgresql-42.5.3.jar:42.5.3]
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:152) ~[postgresql-42.5.3.jar:42.5.3]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-5.0.1.jar:na]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) ~[HikariCP-5.0.1.jar:na]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:39) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3423) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:4058) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:103) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:612) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:483) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:480) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:329) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
I'm expecting the save correctly save into the table but there is a problem.
Any help is appreciated!

Custom ConstraintValidator not invoked before persist

#Target({TYPE, ANNOTATION_TYPE, FIELD})
#Retention(RUNTIME)
#Constraint(validatedBy = {UniqueNameValidator.class})
#Documented
public #interface UniqueName {
String message() default "Unique name constraint";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class UniqueNameValidator implements ConstraintValidator<UniqueName, Object> {
#Override
public void initialize(UniqueName constraintAnnotation) {
System.out.println("UniqueNameValidator -> initialize() method invoked!");
}
#Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
System.out.println("UniqueNameValidator -> isValid method invoked!");
return true;
}
}
#Entity
public class MyClass implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#UniqueName
#Column(name = "NAME")
private String name;
//Getters & Setters
}
The dependencies used in my project are :
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.6.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
Env :
Java 8
WebLogic Server: 12.2.1.2.0
Eclipselink version 2.6.4
After trying many suggestions from SOF i can't figure out why my custom validator is not called before persisting the entity (Validation on class level or field level) !
Any help will be appreciated.

SpringBoot connect to MongoDB

I am learning on Spring boot to insert data into MongoDB and encountered some issues. Please give me some of your advise, thank you.
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 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.onboard.proj</groupId>
<artifactId>onboard</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
UserController.java
#RestController
public class UserController {
#Autowired
MongoService db;
#PostMapping("/create")
public User createNew(#RequestParam("name") String name, #RequestParam("role") String role){
User obj = new User(name, role);
User newObj = db.save(obj);
return newObj;
}
}
MongoService.java
#Service
public class MongoService {
#Autowired
MongoRepository repo;
public User save(User u) {
return repo.save(u);
}
}
MongoRepository.java
public class MongoRepository {
#Autowired
private MongoTemplate template;
public User save(User e) {
if(e != null) {
template.insert(e);
}
return e;
}
}
User.java
#Document
public class User {
#Id
private String id;
//#Field("name")
private String name;
//#Field("role")
private String role;
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getRole() {
return role;
}
public void setName(String name) {
this.name = name;
}
public void setRole(String role) {
this.role = role;
}
public User(String name, String role) {
super();
this.name = name;
this.role = role;
}
public User() {
super();
}
}
I tried to use PostMan and did the following setting, but couldnt reach the UserController. The result from Postman is always 404, NOT FOUND.
Add the annotation #RequestMapping("/") also on class level since Spring requires a mapping for your class also, not only the method.
#RestController
#RequestMapping("/")
public class UserController {
Also you have
#RequestParam("name") String name, #RequestParam("role") String role
but in Postman you pass name and role in JSON body. It is not coded to work like this. You should pass name and role as query parameters in Postman.
#RestController
#RequestMapping("/")
public class UserController {
#Autowired
MongoService db;
#PostMapping("/create")
public User createNew(#RequestParam("name") String name, #RequestParam("role") String role){
User obj = new User(name, role);
User newObj = db.save(obj);
return newObj;
}
}
it is better to use swagger you can get endpoints easily.

Spring Data JPA Primary Key Violation Constraint Not Working

Code and Configuration :
DB used - H2 in Memory database
User Entity :
#Entity
#Table(name = "users")
#Data
#AllArgsConstructor
#NoArgsConstructor
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 455202739064202185L;
#Id // please note is not auto generated but manually generated
#Column(name = "id",unique=true)
#NotNull
private long id;
#Column(name = "firstName")
#NotEmpty(message = "First name is required")
private String firstName;
#Column(name = "lastName")
#NotEmpty(message = "Last name is required")
private String lastName;
#Column(name = "email")
#NotEmpty(message = "Email is required")
#Email(message="Email Must be well formed")
private String email;
}
UserRepository :
public interface UserJpaRepository extends JpaRepository<User, Long> {
}
UserServiceImpl :
this.userJpaRepository.saveAll(users);
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.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.exostar</groupId>
<artifactId>FileUpload</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>FileUpload</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-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
</project>
Issue :
As per the User entity class , #Id is manually generated.
(I have a CSV file which has Id field which is read in User entity)
So Id is not auto generated
Whenever I call this.userJpaRepository.saveAll(users) and even when there is an User entity with Id already existing , the User entity gets overwritten.
That is , Id with same entity gets overwritten with new data.
It has to throw - Unique index or primary key violation error
However, when I try to insert duplicate entry into H2 database MANUALLY , it throws exception - Unique index or primary key violation
I also tried adding unique=true to Id field in User Entity but its not working
Can anybody please help on resolving this issue please ?
Well as it turns out that the behavior that you are seeing is because of the call to em.merge(...) in the save() implementation. Here is what actually happens:
#Transactional
#Override
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null.");
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity); // Update if the entity is not new
}
}
This is a sample code from SimpleJpaRepository implementation. you can use your own query methods for updating the existing query something like this:
#Modifying
#Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);

Map domain class to DTO class using Mapstruct and lombok in SpringBoot application with RestController

The below is my main application class.
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan("com.example.demo")
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}
Controller Class.
#RestController
public class JobAppController {
#Autowired
JobApplicationRepository jobApplicationRepository;
//#Autowired
//private JobApplicationMapper mapper;
JobApplicationMapper mapper = Mappers.getMapper(JobApplicationMapper.class);
#GetMapping("/hello")
public String greeting()
{
return "hello Mr";
}
#PostMapping("/save")
public JobApplicationDto save(#RequestBody JobApplicationDto jobApplicationDto)
{
JobApplication jobApplication = mapper.toEntity(jobApplicationDto);
jobApplication = jobApplicationRepository.save(jobApplication);
return mapper.ToDTO(jobApplication);
}
}
Mapper Interface.
#Mapper
#Component
public interface JobApplicationMapper {
//JobApplicationMapper mapper = Mappers.getMapper(JobApplicationMapper.class);
//({ #Mapping(target="employeeId", source="entity.id"),#Mapping(target="employeeName", source="entity.name")})
JobApplicationDto ToDTO(JobApplication jobApplication);
JobApplication toEntity(JobApplicationDto jobApplicationDto);
}
my 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 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.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jobSearch</groupId>
<artifactId>demo-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-1</name>
<description>Demo project for Spring Boot/JobSearch</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.3.0.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.3.0.Beta2</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
domain class.
#Entity
#Table(name = "Job_Application")
//#Data
//#AllArgsConstructor
//#NoArgsConstructor
public class JobApplication {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id()
private Integer id;
#Column(name = "requisition_id")
private String requisition_id;
#Column(name = "job_posting_source")
private String job_posting_source;
#Column(name = "applied_date")
private Date applied_date;
#Column(name = "company")
private String company;
#Column(name = "current_status")
private String current_status;
#Column(name = "position")
private String position;
#Column(name = "location")
private String location;
//getters and setters follows...
dto class.
/*#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder*/
public class JobApplicationDto {
private Integer id;
private String requisition_id;
private String job_posting_source;
private Date applied_date;
private String company;
private String current_status;
private String position;
private String location;
//getters and setters follows
when try to post data/dto (as JSON) into my db table through postman, the data gets inserted as null values
{
"requisition_id" : "1234",
"job_posting_source" : "indeed",
"applied_date" : "2020-08-15",
"company" : "softInc",
"current_status" : "under review",
"position" : "SE3",
"location" : "Himalayas"
}
the response after insertion is like so
{
"id": null,
"requisition_id": null,
"job_posting_source": null,
"applied_date": null,
"company": null,
"current_status": null,
"position": null,
"location": null
}
There is no error message. not sure what I am missing.
After thorough debug, I realized that there is no issue with the mapper implementation. however since I am using "lombok" for the domain and the dto classes, the getters and setters weren't being generated. So I manually added them now in the code and works as expected now.
PS: I would rate my self as a beginner with this, so any kind of discussion/suggestions are welcome.
I would edit the question now, as the issue is with lombok as to why the getters/setters aren't being generated.
I guess Lombok is missing as annotation processor..
Try:
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
</annotationProcessorPaths>
Checkout this for a working example.
Please note: there are several issues with Lombok / MapStruct. Both are annotation processors. Lombok generates getters / setters, MapStruct uses them. Timing is essential. Hence, MapStruct introduced an SPI to signify when generation is ready.