Calling Save() after findAll() in JPA repository - spring-boot

I am working on an SpringBoot Project and Using the Spring JPA.
I have scenario where I need to fetch all the records and then update them after modification.
For example
#Entity
#Table(name="Employee")
public class Employee{
#ID
#Column(name="ID")
Long id;
#Column(name="age")
private int age;
#Column(name="name")
private String name;
#Embedded
private Address address
//TODO getters and setters goes below
}
and then in the repository
#Repository
public interface EmployeeRepository extends JPARepository<Employee, Long>{
}
and in the service Iam trying as below:
#Service
public class EmployeeService{
#Autowired
EmployeeRepository repository;
#Transactional
public void updateEmployee(){
List<Employee> list = repository.findAll();
for(Employee employee :list) {
employee.setAge(employee.getAge()+4);
repository.save(employee); //This is not working.
}
}
}
Save is neither working nor throwing any error.I have also tried saveAndFlush() but not working. Can someone please help me. I want my objects to get updated.

I tried to recreate your issue, but i cant reproduce your error.
My entities get updated with this perfectly fine.
You say you are doing more logic than this, have you tried printing out your entities after you have made the save, to see if something has been updated, and that it fails in another place in your code?
The code above for me updates all entities as expected :)
logging.level.org.hibernate.SQL=TRACE
Add this to application.properties / yaml file for more tracing of SQL statements

Related

when I create my rest service in spring and mysql generates a table instead of consuming the one I have

I am creating a repository:
#Repository
public interface UserRepository extends JpaRepository<UserRest, String>{
}
and I create a UserResourceTest rest controller:
#RestController
public class UserRestResource {
#Autowired
private UserRepository userRepository;
#GetMapping("/userrest")
public List<UserRest> userAll() {
return userRepository.findAll();
}
}
This generates two classes {user_rest, hibernate_sequence}.
instead of consuming userrest.
Can someone help me what am I doing wrong?
Add in model class UserRest annotation #Table parameter name = userrest
#Entity
#Table(name = "userrest")
public class UserRest
Check out Hibernate: Automatically creating/updating the db tables based on entity classes and How to turn off hbm2ddl?
And change your persistence.xml or config class accordingly! (hibernate.hbm2ddl.auto should be none)

I can do PUT but not POST with Spring Data Rest?

I have two simple entity like this:
public class Agent extends BasedEntity {
private String firstname;
private String lastname;
#ManyToOne
#JoinColumn(name="agency_id", nullable=true)
Agency agency;
}
and
public class Agency extends BasedEntity {
private String name;
private String address;
#OneToMany(mappedBy="agency")
private Set<Agent> agents;
}
#RepositoryRestResource
public interface AgencyRespository extends JpaRepository<Agency, Long> {
}
#RepositoryRestResource
public interface AgentsRespository extends JpaRepository<Agent, Long> {
}
When I do a PUT with
https://localhost:8080/api/v1/agents/64/agency
body:https://localhost:8080/api/v1/agencies/50
it goes through but if I do a POST to
https://localhost:8080/api/v1/agents/64/agency
body:https://localhost:8080/api/v1/agencies/50
I get a
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
You are using an old version of Spring Data Rest. POST is allowed from 2.3.x.
The latest version is 3.2.x. You should definetely ugrade to a newer version...
----------- Edit
I've just realized that the exception is NOT the inner HttpRequestMethodNotSupportedException from the RepositoryPropertyReferenceController class, but the 'default' org.springframework.web.HttpRequestMethodNotSupportedException.
This exception is never raised directly from the SRD package.
Maybe you have a filter which deny POST request or some kind of security settings.

Using #Query witouht extends from JpaRepository

I am trying to execute system request using #Query. So, I do not have to extends JpaRepository and create an entity for no purpose.
I get this error:
Field myDAO in myPackage.impl.MyService required a bean of type 'myPackage.dao.MyDAO' that could not be found.
At MyService, I autowired MyDAO.
public class MyService implements IMyService {
#Autowired
private MyDAO myDAO;
#Override
public List<String> getAllTablesName() {
return myDAO.getAllTablesName();
}
}
I try to add #Repository but nothing is changed
#Repository
public interface MyService{
#Query(value ="SHOW TABLES FROM :tableName",nativeQuery = true)
public List<String> getAllTablesName(#Param("tableName") String tableName);
}
How can I solve this problem ?
While you do not have to extend JpaRepository you'll at least have to extend Repository
If you really don't have an entity you probably shouldn't use JPA in the first place which is all about mapping entities to database tables.
If you just want to execute statements a better fit might be a simple class with an injected JdbcTemplate or NamedParameterJdbcTemplate.

Spring Boot JPA #Transactional #Service does not update, but #Transactional in controller does

I have a very basic Spring Boot/JPA stack app, with a controller, service layer, and repository that does not persist updates as I understand it should.
A trivial Entity:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
protected Customer() {}
public Customer(String name) { this.name = name; }
// standard getters,setters //
}
A trivial Repository:
#Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {}
A simple Service layer:
// If the service is #Transactional and the controller is not, the update does NOT occur
#Transactional
#Service
public class CustomerService {
private static final Logger LOG = getLogger(CustomerService.class);
#Autowired
private CustomerRepository customerRepository;
boolean updateCustomerName(Long id, String name) {
Customer customer = customerRepository.findOne(id);
if (customer == null) { return false; }
// Modifies the entity
customer.setName(name);
// No explicit save()
return true;
}
}
And a REST controller that uses it all:
// If the controller is #Transactional and the service is not, the update occurs
#RestController
#RequestMapping("/mvc")
public class CustomerController {
#Autowired
private CustomerService customerService;
#RequestMapping(path = "{id}", method = RequestMethod.PUT)
public ResponseEntity updateCustomerName(#PathVariable Long id, #RequestParam("name") String name) {
customerService.updateCustomerName(id,name);
return ResponseEntity.noContent().build();
}
}
These are wired together with a simple one-liner SpringBootApplication
I have SQL debug logs enabled and see the selects, update, etc.
With the code above: When the service method is invoked by the controller, the modified entity is not persisted. SQL logs show the select of the entity but no update.
There is also no update if nothing is marked #Transactional
However, simply by moving the #Transactional annotation from the service class to the controller class, the SQL update does occur.
If I add an explicit customerRepository.save(customer) to the service method, the update also occurs. But my understanding is that the ORM should automatically save modified persistent entities.
I'm sure the issue has something to do with the EntityManager lifecycle in the web request, but I'm puzzled. Do I need to do additional configuration?
Complete example at https://github.com/monztech/SO-41515160
EDIT: This was solved, see below. Per the Spring spec #Transactional does not work in package-private methods and mistakenly did not make the update service method public.
The update will occur if the method is public and the service class has the #Transactional annotation.
I do have another question, however. Why is the #Transactional annotation necessary? (the update does not occur without it) Shouldn't the entity manager still persist the object because of the open session in view mechanism that Spring uses, independent of any transaction?
Make your updateCustomerName method public.

spring4 beans injection in bean constructor using #Autowired

I have Class object constructor where one of parameters is Long parent_id cause object is self related as follow:
public class Folder {
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Folder parent;
}
When I try to deserialize with Gson I have to create object using Gson. Using parent_id I would like to creat new object of Folder to apply it to parent element.
When I try to do:
#Transient #Autowired public Folder folderDao;
someMethod() {
folderDao.get(9L);
}
My dao class:
#Override
public T get(Long id) {
System.out.println("_Trying to get by id...");
return (T) getCurrentSession().get(entityClass, id);
}
I got a NullPointerException
and this line is not excecuted: System.out.println("_Trying to get by id...");
I dont know why. Can anyone help me? What Am I doing wrong with Spring Injection.
By the way: My controllers have #Transactional annotation
Seems that skeletonElementDao is null.
Should you autowire the dao, not the folder?
#Autowired
private SkeletonElementDao skeletonElementDao;
instead of
#Transient #Autowired public Folder folder;

Resources