I am working on a Spring Boot project and decided to use MongoDB . I just want to generate sequence number in MongoDB. So even if 100s of different clients trying to do that, I do not want to conflict any generated number. Is there any way to do that ?
Also I tried to make something like this :
SequenceNumber sequenceNumber;
String SEQUENCE_NAME = "example";
sequenceNumber = mongoOperations.findAndModify(query(where("_id").is(SEQUENCE_NAME)),
new Update().inc("number", 1), options().returnNew(true).upsert(true),
SequenceNumber.class);
return sequenceNumber.getNumber();
Is this correct ?
Thanks for answers !
https://www.javaprogramto.com/2019/05/spring-boot-mongodb-auto-generated-field.html
First, create a collection that will store the auto-incremented value in it. This can be created using either the mongo shell or MongoDB Compass
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection = "database_sequences")
public class DatabaseSequence {
#Id
private String id;
private long seq;
public DatabaseSequence() {}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getSeq() {
return seq;
}
public void setSeq(long seq) {
this.seq = seq;
}
}
Let’s then create a users_db collection. This collection stores the users that are being used.
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection = "users_db")
public class User {
#Transient
public static final String SEQUENCE_NAME = "users_sequence";
#Id
private long id;
private String firstName;
private String lastName;
private String email;
public User() { }
public User(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public long getId() {
return id;
}
public void setId(long 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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public String toString() {
return "User{" + "id=" + id + ", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' + ", email='" + email + '\'' + '}';
}
Related
I'm having a problem when i try to create a table using Spring Boot any mysql it seems that Spring boot is not creating table,tried various solutions including:
I'm using windows 10,and in MySql Workbench for the current user all the privileges are granted.Even tried default:
root
root
and it doesnt work
#EntityScan(basePackage={""})
Here is my class:
#Entity
public class Student {
#Id
private long id;
private String firstName;
private String lastName;
private String email;
private int age;
public Student(){
System.out.println("student executed");
}
public Student(long id, String firstName, String lastName, String email, int age) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.age = age;
}
public long getId() {
return id;
}
public void setId(long 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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public String toString() {
return "Student{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
and application.properties:
server.port=8080
spring.datasource.username=newuser
spring.datasource.password=
spring.datasource.url=jdbc:mysql://localhost:3306/spring
spring.jpa.hibernate.ddl-auto=create
spring.jpa.generate-ddl=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.format_sql=true
starting application standard Spring boot way.
the Main Class:
#EntityScan("com.example.demo.models")
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
enter image description here
Thanks for any tip.
I created a new project from Spring Initializr,and used Java 8 instead of Java 11,and it seems it worked,i did to update any maven dependency that i was having and re-checked for newest versions.
I'm having java version "1.8.0_261"
installed so thanks guys for your effort!
I have Entity with 3 fields: id, lastname and phoneNumber. I want to create method which works for update all fields or only one or two.
I use Hibernate and JPA Repository.
When I try to update all fields everything works well but when for example i want to update only lastname without changing of phoneNumber I have in output null insted of old phoneNumber.
Here is my method from Controller:
#PutMapping("/students/update/{id}")
public String updateStudentById(#ModelAttribute Student student, #ModelAttribute StudentDetails studentDetails,
String lastname, String phoneNumber,
#PathVariable Long id) {
Optional<Student> resultOptional = studentRepository.findById(id);
//Student result =resultOptional.get();
resultOptional.ifPresent((Student result) -> {
result.getStudentDetails().setPhoneNumber(studentDetails.getPhoneNumber()); result.getStudentDetails().setLastname(studentDetails.getLastname());
studentRepository.save(result);
});
return "Student updated";
}
The class for update:
#DynamicUpdate
#Entity
public class StudentDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name="lastname")
private String lastname;
#Column(name="phone_number")
private String phoneNumber;
public StudentDetails() {
}
public StudentDetails(Long id, String lastname, String phoneNumber) {
this.id = id;
this.lastname = lastname;
this.phoneNumber = phoneNumber;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
The class which has relation with StudentDetails:
#Entity
#Table(name = "student")
#DynamicUpdate
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "email")
private String email;
//#OneToMany(mappedBy = "student")
#ManyToMany
#JoinTable(name="course_student",joinColumns = #JoinColumn(name="student_id"),
inverseJoinColumns = #JoinColumn(name="course_id"))
private List<Courses> courses;
#OneToOne(cascade = CascadeType.ALL)
// #JoinColumn(name="studen/_details_id") // with this we have dobule student_details column
private StudentDetails studentDetails;
public List<Courses> getCourses() {
return courses;
}
public void setCourses(List<Courses> courses) {
this.courses = courses;
}
public StudentDetails getStudentDetails() {
return studentDetails;
}
public void setStudentDetails(StudentDetails studentDetails) {
this.studentDetails = studentDetails;
}
// Methods for StudentViewController
public String getLastname(){
return studentDetails.getLastname();
}
public String getPhoneNumber(){
return studentDetails.getPhoneNumber();
}
public Student() {
}
public Student(String name, String email, StudentDetails studentDetails) {
// this.id = id;
this.name = name;
this.email = email;
this.studentDetails = studentDetails;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
'}';
}
}
I was looking for solution and I added #DynamicUpdate but still it doesn't work.
Your code works properly. When you only provide lastName parameter in your request, then the phoneNumber parameter will be mapped to null so you override the phoneNumer property in your entity with this null value.
Change the code in the following way:
resultOptional.ifPresent((Student result) -> {
if(studentDetails.getPhoneNumber()!=null) {
result.getStudentDetails().setPhoneNumber(studentDetails.getPhoneNumber());
}
if(studentDetails.getLastname()!=null) {
result.getStudentDetails().setLastname(studentDetails.getLastname());
}
studentRepository.save(result);
});
Unfortunately it raises an other problem: How will you delete these fields? (How can you set them explicitly to null? )
A possible solution if you check for the "" (empty string) and set the property to null if the parameter is empty string.
It will be a quite messy code anyway...
You should consider using the Spring Data Rest package. It automatically creates all of the standard REST endpoints for your entities and handles all of these PUT/PATCH/POST/DELETE issues out of the box.
why don't you just set the params of your request in you setters?
resultOptional.ifPresent((Student result) -> {
result.getStudentDetails().setPhoneNumber(phoneNumber);
result.getStudentDetails().setLastname(lastname);
studentRepository.save(result);
});
You forget set #OneToOne mapping in StudentDetails - StudentDetails also need field of type Student which will be annotated #OneToOne.
Also you have to ensure, that all of entity fields will be filled - read more about fetch types.
I have the following JPA models:
Issue
#Entity
public class Issue {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String title;
private String text;
#ManyToOne
#JoinColumn(name="user_id")
private User user;
public Issue() {}
public Issue(String title, String text) {
this.title = title;
this.text = text;
}
public long getId() {
return id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public String toString() {
return "Issue [id=" + id + ", title=" + title + ", text=" + text + ", user=" + user + "]";
}
}
User
#Entity
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String username;
private String firstname;
private String lastname;
public User() {}
public User(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
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;
}
#Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", firstname=" + firstname + ", lastname=" + lastname
+ "]";
}
}
And an Issue repository that extends PagingAndSortingRepository and contains the method List<Issue> findByUser(User user); See below:
public interface IssueRepository extends PagingAndSortingRepository<Issue,Long> {
List<Issue> findByUser(User user);
}
I'm trying to find a way to navigate these relationships with HTTP calls, namely how do I call findByUser(User user) and get all the issues for that user?
Using the following call I can execute that particular query:
GET http://localhost:8080/issues/search/findByUser
But I'm unclear what I should be providing as the User? Do I send the id as a query param? Do I construct an object and send that as a query param? Am I just modeling this the wrong way?
I'd like to get back a JSON list containing all the Issues for this particular User.
Thanks in advance for any help or guidance.
Changing the repository to this solved the issue. The key is to do the lookup based on a field of the User, not the User itself.
public interface IssueRepository extends PagingAndSortingRepository<Issue,Long> {
List<Issue> findByUserUsername(#Param("username") String username);
}
GET http://localhost:8080/issues/search/findByUserUsername?username=jerney
This returns a list of issues.
put another read only column like
#Column(name = "user_id", insertable = false, updatable = false)
private Long userId;
in Issue entity and use findByUserId(Long userId) repo method to find it and pass userId parameter(i.e path varible) to controller to do this using http calls.
You can use a simple findOne(Long userId) if you need only one record as its probably faster than query by string field
I can not seems to get hibernate to grab any info from mySQL. I've read everywhere and I feel I am doing this correct, apparently I'm not but my brain has blew trying to understand what I messed up.
Main:
#SpringBootApplication
#ComponentScan("com.luv2code")
#EntityScan("com.luv2code.entity")
#EnableJpaRepositories("com.luv2code.dao")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Controller:
#Controller
public class CustomerController {
private CustomerDAO customerDAO;
#Autowired
public void setCustomerDAO(CustomerDAO customerDAO) {
this.customerDAO = customerDAO;
}
#RequestMapping("/")
public String listCustomers(Model model){
long test = customerDAO.count();
model.addAttribute("answer", test);
List<Customer> customers = customerDAO.findAll();
model.addAttribute("customers", customers);
return "home";
}
}
application.properties:
spring.datasource.url = jdbc:mysql://localhost:3306/web_customer_tracker?useSSL=false
spring.datasource.username=root
spring.datasource.password=metalgear3
spring.datasouce.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.MySQL55Dialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
entitymanager.packagesToScan = com.luv2code.entity.Customer
Entity:
#Entity
#Table(name = "customer")
public class Customer implements Serializable {
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private int id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
public Customer(){}
#Override
public String toString() {
return "Customer{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
'}';
}
public Customer(String firstName, String lastName, String email){
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int 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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
DAO:
#Repository("CustomerDAO")
#Transactional
public interface CustomerDAO extends CrudRepository<Customer, Integer> {
public List<Customer> findAll();
public long count();
}
MySql:
CREATE DATABASE IF NOT EXISTS `web_customer_tracker`;
USE `web_customer_tracker`;
DROP TABLE IF EXISTS `customer`;
CREATE TABLE `customer`(
`id` INT(11) NOT NULL auto_increment,
`first_name` VARCHAR(45) DEFAULT NULL,
`last_name` VARCHAR(45)DEFAULT NULL,
`email` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY(`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 CHARSET=latin1;
INSERT INTO `customer` VALUES
(1, 'David', 'Adams', 'david#luv2code.com'),
(2, 'John', 'Die', 'john#luv2code.com'),
(3, 'Ajay', 'Rao', 'ajay#luv2code.com'),
(4, 'Mary', 'Publiidc', 'mary#luv2code.com'),
(5, 'Maxwell', 'Dixon', 'maxwell#luv2code.com');
I know it's a bit late to respond, but this questions is google friendly.
You don't need to declare findAll() inside CustomerDAO. The interface CrudRepository already does it. On top of that, I recommend implementing JpaRepository repository instead (which extends CrudRepository itself and gives you way more convenience methods for free.
I have done this is the past with mySQL but I need to use Oracle:
This is a very simple register user:
application.properties
#Oracle database setup
spring.datasource.url=jdbc:oracle:thin:#999.999.999.11:1521:d3SID
spring.datasource.username=userName
spring.datasource.password=password
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
server.port = 4000
UserInformation model
#Entity
public class UserInformation {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#Column(name = "firstName")
#Min(2) #Max(15)
#NotNull
private String firstName;
#Column(name = "lastName")
private String lastName;
#Column(name = "userName")
private String userName;
#Column(name = "password")
private String password;
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 String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof UserInformation)) {
return false;
}
UserInformation that = (UserInformation) o;
return id.equals(that.id);
}
#Override
public int hashCode() {
return id.hashCode();
}
#Override
public String toString() {
return "Applicant{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", userName='" + userName + '\'' + ", password='" +
password + '\'' + '}';
}
}
JPA repo
public interface UserLoginRepo extends JpaRepository<UserInformation, Long> {}
Controller method
#RequestMapping(value = "/register", method = RequestMethod.POST)
public UserInformation registerUser(#RequestBody UserInformation user){
return userService.save(user);
}
When I run SELECT * FROM USERINFORMATION; nothing displays.
From my understanding I should not need to set up JPA config since I am doing it in applications.properties.
Did you check if the UserInformation object is coming from request body? As I know you shouldn't use "#RequestBody", just put "UserInformation user" must be in the parameters.