public Flux<PortCall> updateByFindById(String gsisKey, PortCall portCall) {
return portCallRepository.findAllByVesselCode(portCall.getVesselCode())
.collectList().flatMap(list->{
return portCallRepository.saveAll(Flux.fromIterable(list));
});
}
Here I'm trying to invoke saveAll() of SimpleReactiveMongoRepository i.e public Flux saveAll(Iterable entities)
Don't you want:
public Flux<PortCall> updateByFindById(String gsisKey, PortCall portCall) {
return portCallRepository.saveAll(
portCallRepository.findAllByVesselCode(portCall.getVesselCode())
);
}
Related
My scenario is need yo track entity property changes. I have used Hibernate PostUpdateEventListener interface to achieve that.
Following is my generic event listener class.
public abstract class EventListener<DOMAIN extends BaseModel> implements PostUpdateEventListener {
public abstract LogSupport getService();
public abstract BaseModel getLogDomain(DOMAIN domain);
#SuppressWarnings("unchecked")
private DOMAIN getDomain(BaseModel model) {
return (DOMAIN) model;
}
public void postUpdate(PostUpdateEvent event, BaseModel model) {
getService().createUpdateLog(getDomain(model), getPostUpdateEventNotes(event));
}
private String getPostUpdateEventNotes(PostUpdateEvent event) {
StringBuilder sb = new StringBuilder();
for (int p : event.getDirtyProperties()) {
sb.append("\t");
sb.append(event.getPersister().getEntityMetamodel().getProperties()[p].getName());
sb.append(" (Old value: ")
.append(event.getOldState()[p])
.append(", New value: ")
.append(event.getState()[p])
.append(")\n");
}
System.out.println(sb.toString());
return sb.toString();
}
}
And this is my custom entity listener.
#Component
public class AssetEventListener extends EventListener<Asset> {
private static final long serialVersionUID = -6076678526514705909L;
#Autowired
#Qualifier("assetLogService")
private LogSupport logSupport;
#Override
public LogSupport getService() {
AutowireHelper.autowire(this, logSupport);
return logSupport;
}
#PostPersist
public void onPostInsert(PostInsertEvent event) {
if (event.getEntity() instanceof BaseModel){
super.postPersist( event, (BaseModel) event.getEntity() );
}
}
#Override
public void onPostUpdate(PostUpdateEvent event) {
if (event.getEntity() instanceof BaseModel){
super.postUpdate( event, (BaseModel) event.getEntity() );
}
}
#Override
public BaseModel getLogDomain(Asset domain) {
return domain;
}
#Override
public boolean requiresPostCommitHanding(EntityPersister persister) {
return false;
}
}
And I called it from #EntityListeners
#Entity
#Table(name = "tbl_asset")
#EntityListeners({ AssetEventListener.class })
public class Asset extends BaseModel {
}
Listener not call when update the entity. Any help would be greatly appreciated.
Thanks,
I have simple RestController that return CollectionModel:
#RequestMapping("/test")
public ResponseEntity<?> index() {
List<DemoEntity> all = Arrays.asList(new DemoEntity(1L, "first"),
new DemoEntity(2L, "second"),
new DemoEntity(3L, "third"));
List<EntityModel<DemoEntity>> list = new ArrayList<>();
all.forEach(demoEntity -> list.add(new EntityModel<>(demoEntity)));
CollectionModel<EntityModel<DemoEntity>> collectionModel = new CollectionModel<>(list);
return ResponseEntity.ok(collectionModel);
}
DemoEntity has only two fields, id and name. SecondEntity is the same.
I am trying to use RepresentationModelProcessor:
#Configuration
public class SpringDataRestConfig {
#Bean
public RepresentationModelProcessor<EntityModel<DemoEntity>> demoEntityProcessor() {
return new RepresentationModelProcessor<EntityModel<DemoEntity>>() {
#Override
public EntityModel<DemoEntity> process(EntityModel<DemoEntity> entity) {
return new MyHateoasEntityModel<>(entity.getContent(), entity.getLink("self").orElse(new Link("self")));
}
};
}
#Bean
public RepresentationModelProcessor<CollectionModel<EntityModel<DemoEntity>>> demoEntitiesProcessor() {
return new RepresentationModelProcessor<CollectionModel<EntityModel<DemoEntity>>>() {
#Override
public CollectionModel<EntityModel<DemoEntity>> process(CollectionModel<EntityModel<DemoEntity>> collection) {
// return new CollectionModel<>(collection.getContent());
return new MyHateoasCollectionModel<>(collection.getContent());
}
};
}
#Bean
public RepresentationModelProcessor<EntityModel<SecondEntity>> secondEntityProcessor() {
return new RepresentationModelProcessor<EntityModel<SecondEntity>>() {
#Override
public EntityModel<SecondEntity> process(EntityModel<SecondEntity> entity) {
return new MyHateoasEntityModel<>(entity.getContent(), entity.getLink("self").orElse(new Link("self")));
}
};
}
#Bean
public RepresentationModelProcessor<CollectionModel<EntityModel<SecondEntity>>> secondEntitiesProcessor() {
return new RepresentationModelProcessor<CollectionModel<EntityModel<SecondEntity>>>() {
#Override
public CollectionModel<EntityModel<SecondEntity>> process(CollectionModel<EntityModel<SecondEntity>> collection) {
// return new CollectionModel<>(collection.getContent());
return new MyHateoasCollectionModel<>(collection.getContent());
}
};
}
}
One thing here is that I want to use my own classes MyHateoasEntityModel and MyHateoasCollectionModel. They are quite simple:
public class MyHateoasEntityModel<T> extends EntityModel<T> {
private T entity;
public MyHateoasEntityModel(T entity, Iterable<Link> links) {
super(entity, Collections.emptyList());
this.entity = entity;
}
public MyHateoasEntityModel(T entity, Link... links) {
this(entity, Collections.emptyList());
}
}
public class MyHateoasCollectionModel<T> extends CollectionModel<T> {
public MyHateoasCollectionModel(Iterable<T> content, Link... links) {
super(content, Collections.emptyList());
}
}
The question is that when the controller is called, the demoEntityProcessor, demoEntitiesProcessor methods are called in turn. And this is what i want from the application. But then, somehow, secondEntitiesProcessor is called, but shouldn't.
Earlier, spring boot 1.5.17 was used, and everything works fine.
All code on: https://github.com/KarinaPleskach/Hateoas
I tried but could not find the right answer could you pleasehelp me out?
Table is creating but data is not getting inserted.I fixed the above error but data is not inserting in db for Hibernatetemplate save().
#Transactional(propagation=Propagation.REQUIRED,readOnly=false)
public class StudentDaoImplHT implements StudentDao {
private HibernateTemplate ht;
public void setHt(HibernateTemplate ht) {
this.ht = ht;
}
#Transactional
#Override
public int save(Student st) {
int i=(Integer) ht.save(st);;
System.out.println(st.getId());
System.out.println(st.getAddress());
System.out.println(st.getEmail());
System.out.println(st.getName());
return i; }
#Override
public boolean update(Student st) {
ht.saveOrUpdate(st);
return true;
}
#Override
public boolean delete(Student st) {
//ht.delete(st);
return true;
}
#Override
public Student findByPK(int id ) {
Student std=(Student) ht.get(Student.class, id);
return std;
}
#Override
public List<Student> findByAllUsingHQL() {
List<Student> list=(List<Student>) ht.find("from Student");
return list;
}
#Override
public List<Student> findByAllUsingCriteria() {
DetachedCriteria dc=DetachedCriteria.forClass(Student.class);
//dc.setProjection(projection);
//ht.findByCriteria(criteria)
List<Student> list= (List<Student>) ht.findByCriteria(dc);
return null;
}
}
Make sure you have the following property in your hibernate.cfg.xml:
"hibernate.connection.autocommit" true"
property name="hibernate.connection.autocommit" true property
Hope it helps.
I am implementing a simple Movie based CRUD API using Spring WebFlux and Reactive Spring Data MongoDB. I want to make sure that my implementation is correct and that I am properly using Flux and Mono to implement the CRUD operations. I also want to make sure that I am properly handling any errors or null values. I am very new to this programming paradigm and Spring WebFlux, so I am not sure about the correctness of the implementation of the Controller and Service layer, I want to make sure I am adhering to Spring WebFlux and Project Reactor best practices.
#Repository
public interface MovieRepository extends ReactiveMongoRepository<Movie, String> {
Flux<Movie> findByRating(String rating);
}
public interface MovieService {
Flux<Movie> list();
Flux<Movie> findByRating(String rating);
Mono<Movie> update(String id, MovieRequest movieRequest);
Mono<Movie> create(Mono<MovieRequest> movieRequest);
Mono<Movie> read(String id);
Mono<Movie> delete(String id);
}
#Service
public class MovieServiceImpl implements MovieService {
#Autowired
private MovieRepository movieRepository;
#Override
public Flux<Movie> list(){
return movieRepository.findAll();
}
#Override
public Flux<Movie> findByRating(final String rating){
return movieRepository.findByRating(rating);
}
#Override
public Mono<Movie> update(String id, MovieRequest movieRequest) {
return movieRepository.findOne(id).map(existingMovie -> {
if(movieRequest.getDescription() != null){
existingMovie.setDescription(movieRequest.getDescription());
}
if(movieRequest.getRating() != null){
existingMovie.setRating(movieRequest.getRating());
}
if(movieRequest.getTitle() != null) {
existingMovie.setTitle(movieRequest.getTitle());
}
return existingMovie;
}).then(movieRepository::save);
}
#Override
public Mono<Movie> create(Mono<MovieRequest> movieRequest) {
return movieRequest.map(newMovie -> {
Movie movie = new Movie();
if(newMovie.getDescription() != null){
movie.setDescription(newMovie.getDescription());
}
if(newMovie.getRating() != null){
movie.setRating(newMovie.getRating());
}
if(newMovie.getTitle() != null) {
movie.setTitle(newMovie.getTitle());
}
return movie;
}).then(movieRepository::save);
}
#Override
public Mono<Movie> read(String id) {
return movieRepository.findOne(id);
}
#Override
public Mono<Movie> delete(String id) {
Mono<Movie> movie = movieRepository.findOne(id);
movieRepository.delete(id);
return movie;
}
}
#RestController
public class MovieRestController {
#Autowired
private MovieService movieService;
#GetMapping(value = "/movies")
public Flux<ResponseEntity<Movie>> list() {
return movieService.list().map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
#GetMapping(value = "/moviesByRating")
public Flux<ResponseEntity<Movie>> findByRating(
#RequestParam(value = "rating", required = false) final String rating) {
return movieService.findByRating(rating)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
#GetMapping("/movies/{movieId}")
public Mono<ResponseEntity<Movie>> read(
#PathVariable("movieId") final String movieId) {
return movieService.read(movieId)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
#DeleteMapping("/movies/{movieId}")
public Mono<ResponseEntity<Movie>> delete(
#PathVariable("movieId") final String movieId) {
return movieService.delete(movieId)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
#PutMapping("/movies/{movieId}")
public Mono<ResponseEntity<Movie>> update(
#PathVariable("movieId") final String movieId,
#RequestBody final MovieRequest movieRequest) {
return movieService.update(movieId, movieRequest)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
#PostMapping("/movies")
public Mono<ResponseEntity<Movie>> create(
#RequestBody final Mono<MovieRequest> movieRequest) {
return movieService.create(movieRequest)
.map(m -> new ResponseEntity<>(m, HttpStatus.OK));
}
}
class SomeModel extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{some_table}}';
}
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return self::model()->findAll($criteria);
}
}
This method works properly when I call it from controller
SomeModel::model()->getItemByParentId($someVariable)
But now I have 3 very similar to SomeModel models, so I want to put common methods to one class
class CommonModel extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return self::model()->findAll($criteria);
}
}
class FirstModel extends CommonModel
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{first_table}}';
}
}
class SecondModel extends CommonModel
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{second_table}}';
}
}
But get error
The table "CommonModel" for active record class "CommonModel" cannot
be found in the database.
What is wrong?
Try to change:
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return static::model()->findAll($criteria);
}