Spring Boot: How can I reset the entity ID back to 0 every time I make Delete request with client - spring

I have created a server using Java Spring Boot and I made a delete request that deletes all entries in a repository. I tried adding it back and the ID incremented instead of starting back to 0.
#DeleteMapping("/donors")
public String deleteAllDOnors() {
return donorService.deleteAllDonors();
}
#Id
#GeneratedValue
private Long id;
Edit. I tried this so far in a service class:
#PersistenceContext
EntityManager entityManager;
In the same class:
public String deleteAllDonors() {
entityManager
.createNativeQuery("ALTER TABLE SomeTable AUTO_INCREMENT = 1")
.executeUpdate();
donorRepository.deleteAll();
return "All donors removed!";
}
I get a
javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:422) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1668) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]

Not sure what persistence layer you are using but following is an example of JPA on how you can reset it
entityManager
.createNativeQuery("ALTER TABLE SomeTable AUTO_INCREMENT = 1")
.executeUpdate();

Related

How to do findById for autogenerated id

I have a scenario where I am consuming an event and saving the details in the DB. Now the record that is being stored in the database has the id field autogenerated #GeneratedValue(strategy = GenerationType.IDENTITY).
In my test case I need to check if data is getting stored in the DB or not and is as per expectation.
But I am not sure how will I do findById() of SpringBoot Crud/JPA Repository since I do not know what value got generated.
Any help would be appreciated.
Take a look at save method from CrudRepository interface. Spring executes this method in transaction and after its completion Hibernate will generate identifier in returned entity.
Suppose your entity and repository looks as following:
....
public class SomeEntity {
#Id
#GeneratedValue
private Long id;
private String name;
public SomeEntity(String name){
this.name = name;
}
....
}
public interface SomeRepository extends CrudRepository<SomeEntity, Long> {
}
After saving entity:
SomeEntity someEntity = someRepository.save(new SomeEntity("Some entity"));
someEntity.getId() will contain actual record id which can be used further in your tests.
I think you are looking for annotation #DirtiesContext .
It is a Test annotation which indicates that the ApplicationContext associated with a test is dirty and should therefore be closed and removed from the context cache. - javadoc
Read Section 9.3.4 - Here
Check - Example ans below as well:
#Test
#DirtiesContext
public void save_basic() {
// get a course
Course course = courseJpaRepository.findById(10001L);
assertEquals("JPA ", course.getName());
// update details
course.setName("JPA - Updated");
courseJpaRepository.saveOrUpdate(course);
// check the value
Course course1 = courseJpaRepository.findById(10001L);
assertEquals("JPA - Updated", course1.getName());
}
BTW - how you can get the id : simply via getter method from the return type of save
EmployeeDetails employeeDetails = emaployeeService.saveEmployeeDetails(employee);
int temp = employeeDetails.getID()
Related Post : Here

Database default field not retrieved when using #Transactional

I have the following simple entity FileRegistry :
#Getter
#Setter
#Entity
#ToString
#Table(name = "file_store")
public class FileRegistry {
#Id
private String name;
/**
* Creation timestamp of the registry
* This value is automatically set by database, so setter method
* has been disabled
*/
#Setter(AccessLevel.NONE)
#Column(insertable = false, updatable = false)
private LocalDateTime creationDate;
}
The following FileRepository DAO:
#Repository
public interface FileRepository extends JpaRepository<FileRegistry, String> { }
and the following Spring Boot test :
#SpringBootTest(classes=PersistTestConfig.class, properties = { "spring.config.name=application,db"})
#ActiveProfiles("test")
#Transactional
public class FileRepositoryTest {
#Autowired
FileRepository fileRepository;
#Test
void insertFileTest() {
assertNotNull(fileRepository, "Error initializing File repository");
// Check registry before insertion
List<FileRegistry> allFiles = fileRepository.findAll();
assertNotNull(allFiles, "Error retrieving files from registry");
assertThat(allFiles.size(), is(0));
// Insert file
FileRegistry fileRegistry = new FileRegistry();
fileRegistry.setName("Test");
fileRepository.save(fileRegistry);
// Check that the insertion was successful
allFiles = fileRepository.findAll();
assertNotNull(allFiles, "Error retrieving files from registry");
assertThat(allFiles.size(), is(1));
assertEquals("File registry name mismatch", "Test", allFiles.get(0).getName());
System.out.println(allFiles.get(0));
}
}
Persistence configuration class defined as follows :
#Configuration
#EnableAutoConfiguration
#EnableTransactionManagement
#EnableJpaRepositories
public class PersistTestConfig {
}
The table file_store defined in H2 as :
CREATE TABLE file_store (name VARCHAR NOT NULL, creation_date TIMESTAMP(3) DEFAULT NOW() NOT NULL, CONSTRAINT file_store_pk PRIMARY KEY (name));
Everything works fine except that when I use #Transactional at test level (mainly to benefit from rollbacks i.e. db cleanup on each test) a null value is fetched for the creationDate field :
FileRegistry(name=Test, creationDate=null)
When I remove #Transactional from the test class, the fetched value contains the date as computed by H2 :
FileRegistry(name=Test, creationDate=2019-03-07T17:08:13.392)
I've tried to flush and merge manually the instance to no avail. To be honest, right now I'm a little bit lost on how #Transactional really works, in fact reading the docs and inspecting the code, the underlying JpaRepository implementation (SimpleJpaRepository) is annotated as #Transactional(readOnly = true).
A little help on this subject would be very appreciated.
Ok, figured it out.
Simply issuing a refresh entityManager.refresh(allFiles.get(0)); solves the issue.
I tested also using Hibernate's #Generated(INSERT) specific annotation in the entity creationDate field and it also worked fine.
By the way I've eventually decided to drop this thing in favor of using Spring Data's JpaAuditing features and annotating the field with #CreatedDate annotation to fill the value instead of relying on DB date (by the way, production-wise, you probably shouldn't rely on DB time). To me this is feels more, let's say, "correct" and springy way of doing things.

Spring JPA CrudRepository save(Entity) is returning 0 in id field

I am adding spring JPA/Hibernate 5 to an old project. I am running CrudRepository .save(Entity) method against a Mainframe/DB2 table. The row is inserted just fine, but returnedEntity.getIdColumn() has 0 in it. I really need the ID for further processing. Could somebody please help? Thank you very much!
#Entity
Table(name="MY_TABLE")
public class myClass {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID_COLUMN")
private Long idColumn;
...
}
Identity is the only strategy type that worked.
Here is the Service class:
#Transactional
public Entiry insertEntity(Entity originalEntity) {
return MyRepository.save(originalEntity);
}
Runner class:
Entity originalEntity = createEntity();
Entity returnedEntity = ServiceClass.insertEntity(originalEntity);
System.out.println(originalEntity.getIdColumn());
System.out.println(returnedEntity.getIdColumn());
My guess is that you're trying to get an ID before your transaction was flushed to DB. Thus JPA doesn't know what id will be assigned and returns 0.
Edited:
I'd recommend to have something like this:
#Transactional
public Entity save( .....) {
//some code
repository.save(entity);
//some code
return entity;
}
Transaction will be flushed at the end of this method and entity which will be returned from it should have a real id.
Turned out my table had an id sequence generator already defined in the DB. So, after I changed it to generationType.SEQUENCE it worked nicely.
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_TABLE_SEQ")
Recently, I've faced with similar issue.
In my case, the new entity has been passed from UI and ID was 0 instead of NULL (since the type of ID was primitive on Java side). Therefore Hibernate didn't use right save strategy.
Eventually, I changed the type from long to Long and it helped:
private long id;
private Long id;
Also update method was changed from:
#PutMapping("/{id}")
public T update(#PathVariable ID id, #Valid #RequestBody T entity) {
this.getService().update(entity);
return entity;
}
to:
#PutMapping("/{id}")
public T update(#PathVariable ID id, #Valid #RequestBody T entity) {
return this.getService().update(entity);
}
P.S.: When entity ID was 0, Hibernate was using merge strategy, however, it should persist strategy for new Entities instead (link for implementation of save method).

Transaction does not retrieve on time data

I have a project with many services. I'm using pure jpa with jersey in my project.
I use entityManager, entityTransaction and entityManagerFactory in this way: for each service I get an EntityManager from DBManager.getEntityManager() and get and entityTransaction from its entityManager
public class DBManager {
public static EntityManager getEntityManager() {
return Persistence.createEntityManagerFactory("projectDataSource").getEntityManager();
}
In each method that need transaction, first I check transaction != null and transaction is not active
Then I begin the transaction.
I evict cache and after all of this I do my job: in this example I get all active users from database, and my service that returns users list to client.
One of my services is : #getUsersService
public class GetUsersServiceImpl {
private static EntityManager entiyManager = DBManager.getEntityManager();
private static EntityTransaction entityTransaction = entityManager.getTransaction();
public List<User> getUsers()
if (transaction != null && !transaction.isActive())
transaction.begin()
entityManager.getEntityMangerFactory().getCache().evictAll();
return entityManger.createQuery("SELECT u FROM USER u WHERE u.isActive = true").getResultList();
}
This code works but not always!
I have another service that changes the users; this user also works and changes user data in database, but after calling change service when I call getUsers service, it retrieves old database data
Why does this happen?
Is it correct the way I use entityManager and entityTransaction ...

I need help for persisting into oracle database

There is a problem about generating id while persisting into database.
I added the following code to my jpa entity file, however I'm getting 0 for personid.
#Id
#Column(unique=true, nullable=false, precision=10, name="PERSONID")
#SequenceGenerator(name="appUsersSeq", sequenceName="SEQ_PERSON", allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "appUsersSeq")
private long personid;
EjbService:
#Stateless
public class EjbService implements EjbServiceRemote {
#PersistenceContext(name = "Project1245")
private EntityManager em;
#Override
public void addTperson(Tperson tp) {
em.persist(tp);
}
}
0 is default value for long type. The id will be set after invoking select query for the related sequence, which commonly is executed when you persist the entity. Are you persisting the entity? In case yes, post the database sequence definition to check it.

Resources