Streamlining CRUD Development with JHipster’s Entity Sub‑generator
Learn how JHipster’s entity sub‑generator creates a complete backend‑frontend CRUD slice with one command, see a concrete Book entity example, and understand its limits and verification steps.
13 Sept 2025, 11:43 UTC

The problem: repetitive boilerplate for every new domain object
When you start a new feature in a JHipster project, you need a JPA entity, a Spring Data repository, a service layer, a REST controller, DTOs with MapStruct mappers, and the matching Angular module, routing, components and service. Writing all of this by hand is error‑prone and consumes time that could be spent on business logic.
Thesis: the JHipster entity sub‑generator creates a full‑stack CRUD slice in one command, letting you focus on domain specifics
The sub‑generator (jhipster entity <Name>) produces a coherent set of backend and frontend artefacts that are immediately runnable. It also adds the necessary Liquibase changelog and, optionally, test skeletons. The generated code respects JHipster’s conventions, so the rest of the application (security, pagination, filtering) works out of the box.
Worked example: adding a Book entity to a monolith
Ensure you are in an existing JHipster monolith (created with
jhipsterand using the default stack: Spring Boot, Angular, H2/PostgreSQL).Run the sub‑generator, specifying the fields you need:
jhipster entity Book ? Do you want to add a field to your entity? Yes ? Field name: title ? Field type: String ? Validation rules: (leave blank) ? Do you want to add another field? Yes ? Field name: author ? Field type: String ? Do you want to add another field? Yes ? Field name: publishedDate ? Field type: LocalDate ? Do you want to add another field? No ? Do you want to add service class methods? Yes ? Do you want to generate a DTO? Yes ? Do you want to generate MapStruct mappers? Yes ? Do you want to generate a Spring Data JPA repository? Yes ? Do you want to generate a Spring MVC REST controller? Yes ? Do you want to generate Angular code? Yes ? Do you want to generate Cypress protractor tests? NoThe command creates (or updates) the following files (paths are relative to the project root):
src/main/java/com/mycompany/myapp/domain/Book.java– JPA entity with@Entity, fields, getters/setters, equals/hashCode.src/main/java/com/mycompany/myapp/repository/BookRepository.java– Spring Data JPA repository.src/main/java/com/mycompany/myapp/service/BookService.javaandBookServiceImpl.java– service interface and implementation.src/main/java/com/mycompany/myapp/web/rest/BookResource.java– REST controller exposing/api/bookswith CRUD operations.src/main/java/com/mycompany/myapp/service/dto/BookDTO.javaandBookMapper.java– DTO and MapStruct mapper.src/main/webapp/app/entities/book/book.module.ts,book.route.ts,book.component.ts(list),book-detail.component.ts,book-update.component.ts,book-delete-dialog.component.ts– Angular module and components.src/main/webapp/app/entities/book/book.service.ts– Angular service that usesHttpClientto call the REST endpoints.src/main/resources/config/liquibase/changelog/20240101000000_added_entity_book.xml– Liquibase changelog creating thebooktable.
Verify the backend:
./mvnw # or ./gradwl # Application starts on http://localhost:8080 curl -i http://localhost:8080/api/books # Expected: HTTP 200 with [] (empty list) # To create a book: curl -X POST http://localhost:8080/api/books \ -H 'Content-Type: application/json' \ -d '{"title":"The Hobbit","author":"J.R.R. Tolkien","publishedDate":"1937-09-21"}' # Expected: HTTP 201 with the created BookDTO in the bodyVerify the frontend:
# In a separate terminal npm start # serves Angular UI on http://localhost:9000 # Open the UI, navigate to Entities → Book # You should see an empty list, a “Create” button, and be able to create, edit, view and delete books without console errors.
Trade‑off and limitation: generated code can be overwritten
The sub‑generator is designed to be re‑run. If you execute jhipster entity Book again, any file that lies inside the JHipster‑managed comment blocks (marked with // jhipster-needle* in Java or /* jhipster-needle*/ in TypeScript) will be regenerated, discarding manual edits made outside those blocks. To preserve custom logic, place it inside the designated sections or move it to a separate class that you extend or delegate to. Additionally, the generator does not fully support complex inheritance hierarchies or composite primary keys; those cases require manual adjustments to the JPA entity and related layers.
Practical way to check the result and roll back if needed
After generation, inspect the git status:
git status
# Should show new/modified files under src/main/... and src/main/webapp/app/entities/book/...
# To see exactly what was added:
git diff --stat
If you need to revert the changes (for example, after a mistaken field), you can simply reset the generated files:
git checkout HEAD -- src/main/java/com/mycompany/myapp/domain/Book.java
# Repeat for each generated path, or revert the whole commit:
Because the operation only adds or modifies files, a rollback is safe as long as you have not committed unrelated changes in the same commit.
Actionable closing
Use the entity sub‑generator whenever you need a new CRUD resource in a JHipster project. It gives you a clean, testable starting point in seconds, letting you invest your effort in business rules rather than boilerplate. Remember to keep custom code inside the JHipster‑managed sections or in separate layers, and verify the generated Liquibase changelog and API endpoints before moving on to UI polishing.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.