How to auto increment mongo db in Spring Boot? - mongodb

I try simple CRUD in Spring Boot with Mongodb. I have problem with id number. How can I auto increment id. I tried but couldn't do it
Is there any simple auto increment way?
Controller
#Autowired
EmployeeRepo repo;
#RequestMapping(value = "home", method = RequestMethod.GET)
public String getHomePage(Model model) {
Employee employee = new Employee();
employee.setId(1);
employee.setName("deniz");
employee.setPassword("123");
repo.save(employee);
...
Employee
#Document(collection = "Employee")
public class Employee {
#Id
private long id;
private String name;
private String password;
// getter and setter

public long getNextSequenceId(String key) {
Query query = new Query(Criteria.where("_id").is(key));
Update update = new Update();
update.inc("seq", 1);
FindAndModifyOptions options = new FindAndModifyOptions();
options.returnNew(true);
SequenceId seqId =
mongoOperation.findAndModify(query, update, options, SequenceId.class);
return seqId.getSeq();
}

Related

JPARepository - delete using date comparison with derived query

I'm trying to use JPARepository in Spring Boot to delete records that are less than a certain date, for for a given userid
Should be something like this Delete * from [table] where expiration_date < [date] and userid = [userid]
I thought I should be able to use one of the automatically generated methods
int deleteByExpiryDateBeforeAndUser(Date date, User user);
But this is generating a Select and not a Delete. What am I doing wrong?
Update
Entity class
#Getter
#Setter
#ToString
#Entity(name = "refresh_token")
public class RefreshToken {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#OneToOne
#JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
#Column(nullable = false, unique = true)
private String token;
#Column(nullable = false)
private Date expiryDate;
public RefreshToken() {
}
}
Repository class
#Repository
public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Long> {
Optional<RefreshToken> findByToken(String token);
#Modifying
void deleteByUserIdAndExpiryDateBefore(Long userId, Date expiryDate);
int deleteByUser(User user);
}
Here's how I'm calling it
#Transactional
public void deleteExpiredTokens(User user) {
refreshTokenRepository.deleteByUserIdAndExpiryDateBefore(user.getId(), new Date());
}
You see a select statement because Spring Data first loads entities by condition.
Then once entities became 'managed' Spring Data issues a delete query for each entity that was found.
If you want to avoid redundant SQL query - you have to consider #Query annotation.
Then your code will look like this:
#Repository
public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Long> {
// ...
#Query(value = "DELETE FROM refresh_token WHERE user_id =:userId AND expiry_date < :expiryDate", nativeQuery = true)
#Modifying
void deleteByUserIdAndExpiryDateBefore(Long userId, Date expiryDate);
//...
}

#Transactional in spring JPA

I have a spring boot application where I need to update a migratedCustomer db table based on userId and phoneNumber.
Since I have to use for loop in the service layer for every update, it is creating a
new transaction and performance is hampered.
how could I make sure only one transaction is created and hence to improve the performance. code is like below
#Entity
#Table(name = "MigratedCustomer")
public class MigratedCustomer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String userId;
private String phoneNumber;
#Temporal(TemporalType.TIMESTAMP)
private Date createdTimestamp;
private int batchNumber;
private String comment;
}
public class MigratedCustomerService {
#Autowired
private UserRepository userRepository;
public void updateMsisdn(List<MigratedCustomer> savedCustomers) {
for (MigratedCustomer savedCustomer : savedCustomers) {
userRepository.updateStatus(savedCustomer.getUserId(),
savedCustomer.getPhoneNumber());
}
}
}
public interface MsisdnRepository extends JpaRepository<Msisdn, Long> {
#Modifying
#Query(value = "UPDATE Msisdn SET status=INACTIVE where userId=:userId and phoneNumber=:phoneNumber",
nativeQuery = true)
void updateStatus(#Param("userId") String userId, #Param("phoneNumber") String phoneNumber);
}

Spring Data JPA order by value from OneToMany relation

I am trying to sort a result by nested collection element value. I have a very simple model:
#Entity
public class User {
#Id
#NotNull
#Column(name = "userid")
private Long id;
#OneToMany(mappedBy = "user")
private Collection<Setting> settings = new HashSet<>();
// getters and setters
}
#Entity
public class Setting {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "userid")
private User user;
private String key;
private String value;
// getters and setters
}
public interface UserRepository extends JpaRepository<User, Long>, QuerydslPredicateExecutor<User> {
}
I want to have a result returned sorted by the value of one setting.
Is it possible to order by user.settings.value where settings.name = 'SampleName' using Spring Data JPA with QueryDSL?
I've used JpaSpecificationExecutor. let's see findAll for example.
Page<T> findAll(#Nullable Specification<T> spec, Pageable pageable);
Before call this method you can create your specification dynamically (where condition) and Pageable object with dynamic Sort information.
For example
...
Specification<T> whereSpecifications = Specification.where(yourWhereSpeficiation);
Sort sortByProperty = Sort.by(Sort.Order.asc("property"));
PageRequest orderedPageRequest = PageRequest.of(1, 100, sortByProperty);
userRepository.findAll(whereSpecifications, PageRequest.of(page, limit, orderedPageRequest));

Hibernate Envers - custom RevisionEntity - how to get record

I have written my custom RevisionEntity class to store additional data (for example username), like below:
#Entity
#RevisionEntity(AuditListener.class)
#Table(name = "REVINFO", schema = "history")
#AttributeOverrides({
#AttributeOverride(name = "timestamp", column = #Column(name = "REVTSTMP")),
#AttributeOverride(name = "id", column = #Column(name = "REV")) })
public class AuditEntity extends DefaultRevisionEntity {
private static final long serialVersionUID = -6578236495291540666L;
#Column(name = "USER_ID", nullable = false)
private Long userId;
#Column(name = "USER_NAME")
private String username;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
I can see that all rows in database are correctly stored, REVINFO table contains also username.
I would like to query database to get detailed information from my custom RevisionEntity, like username.
How can I do it? Is there any supported API to get it?
Lets assume you know the identifier of the entity you're interested in the revision entity metadata for, you can easily query that information using the following approach:
final AuditReader auditReader = AuditReaderFactory.get( session );
List<?> results = auditReader.createQuery()
.forRevisionsOfEntity( YourEntityClass.class, false, false )
.add( AuditEntity.id().eq( yourEntityClassId ) )
.getResultList();
The returned results will contain an Object array, e.g. Object[] where results[1] will hold the revision entity instance which contains the pertinent information your wanting.
For more details, you can see the java documentation comments here
If you only have the revision number, you can access just the revision entity instance directly by:
// I use YourAuditEntity here because AuditEntity is actually an Envers class
YourAuditEntity auditEntity = auditReader
.findRevision( YourAuditEntity.class, revisionId );
For more details on the AuditReader interface, you can see the java documentation here

need Spring Data JPA resource entry to make one many rest call

Using Spring Data jpa and Spring Data Rest I could able to get basic CRUD operations to work. But I am facing problem with one to many (owner -> car(s)) relationship. Can any one help me in this.
Owner.java
#Entity
#Table(name = "OWNER")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Owner implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "age")
private Integer age;
#OneToMany(mappedBy = "owner")
#JsonIgnore
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Car> cars = new HashSet<>();
}
OwnerResource.java
#RestController
#RequestMapping("/api")
public class OwnerResource {
private final Logger log = LoggerFactory.getLogger(OwnerResource.class);
#Inject
private OwnerRepository ownerRepository;
#RequestMapping(value = "/owners",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<Owner> create(#RequestBody Owner owner) throws URISyntaxException {
log.debug("REST request to save Owner : {}", owner);
if (owner.getId() != null) {
return ResponseEntity.badRequest().header("Failure", "A new owner cannot already have an ID").body(null);
}
Owner result = ownerRepository.save(owner);
return ResponseEntity.created(new URI("/api/owners/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert("owner", result.getId().toString()))
.body(result);
}
#RequestMapping(value = "/owners",
method = RequestMethod.PUT,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<Owner> update(#RequestBody Owner owner) throws URISyntaxException {
log.debug("REST request to update Owner : {}", owner);
if (owner.getId() == null) {
return create(owner);
}
Owner result = ownerRepository.save(owner);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert("owner", owner.getId().toString()))
.body(result);
}
#RequestMapping(value = "/owners",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<List<Owner>> getAll(#RequestParam(value = "page" , required = false) Integer offset,
#RequestParam(value = "per_page", required = false) Integer limit)
throws URISyntaxException {
Page<Owner> page = ownerRepository.findAll(PaginationUtil.generatePageRequest(offset, limit));
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/owners", offset, limit);
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
#RequestMapping(value = "/owners/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<Owner> get(#PathVariable Long id) {
log.debug("REST request to get Owner : {}", id);
return Optional.ofNullable(ownerRepository.findOne(id))
.map(owner -> new ResponseEntity<>(
owner,
HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
}
OwnerRepository.java
/**
* Spring Data JPA repository for the Owner entity.
*/
public interface OwnerRepository extends JpaRepository<Owner,Long> {
}
The basic crud operation is working fine for Owner. But now I need to get all cars of a particular owner for that I need to add one rest call entry in OwnerResource.java and a method entry in OwneRepository.java. I tried different ways but getting many errors and is not working. The following is what I tried.
In OwnerRepository.java
Owner findAllByOwnerId(Long id);//But eclipse shows error here for this method
In OwnerResource.java
//Get All Cars
#RequestMapping(value = "/{id}/cars",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<Owner> getAll(#PathVariable Long id) {
log.debug("REST request to get All Cars of the Owner : {}", id);
return Optional.ofNullable(ownerRepository.findAllByOwnerId(id))
.map(owner -> new ResponseEntity<>(
owner,
HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
But these two changes are not working out. I am beginner to spring data jpa and spring data rest. Can any one help me in correcting these two so that I can get all cars of the owner.
I believe it shows an error because the findAll returns a different type of object: List, Page, etc...
Try this:
List<Owner> findAllByOwnerId(#Param("id") Long id);
That will return you a list of objects. If you want to return with pagination, than you need this instead:
Page<Owner> findAllByOwnerId(#Param("id") Long id, Pageable pageable);
I hope this helps, let me know how it works for you.