From Laravel to Spring Boot: overview to start quickly
If you are curious about trying Spring Boot but you only have experience in Laravel this article may help you start faster than ever. This is not a tutorial but a very short overview with a little code to get you a controller and a mysql db connection. At the end of the articles you will also find one article and some video that will be really helpful to you as an absolute beginner.
To create a Spring Boot app you go on https://start.spring.io/, give a name to your project, add the dependencies you need (as a beginner, use maven) and you're good to go.
As beginner Spring Boot webdev and for the purpose of this article the dependecy to start are Spring Web, jdbc and the mysql driver.
Routes
Anything you put into src/main/resources/static will be served directly, so if you add a static about.html it will be returned at localhost:8080/about.html. If you want something like Blade there is Thymeleaf, but to be honest I've used Spring Boot as a backend for SPAs.
To have a route you create a class. For example let's say you are serving informations about cats, you can create a CatController
class, then you put the @Controller
or the @RestController
annotation.
You use @Controller
when you want to return a view to be resolved by Thymeleaf (or colleagues), otherwise you use @RestController
for your REST endopoints. You then put annotations like @GetMapping("/photoz")
(for GET requests), @PostMapping("/photoz")
(for POST requests), etc on top of the methods you want to be invoked when the user reaches a certain route.
@RestController
public class CatController {
@GetMapping("/cats")
public String getCats() {
//...
}
@PostMapping("/photoz")
public String postCat() {
//...
}
}
What should methods of @RestController return?
You could return an object directly and it will be turned into json, but to make things more clean and have more consistency when you want to return a different status code or header, etc you want to use the ResponseEntity
class. So your method may look like this:
@GetMapping("/photo")
public ResponseEntity<Cat> getOneCat() {
Cat cat = new Cat();
return ResponseEntity.ok(Cat);
}
What about the Models and the Database?
In Laravel you use eloquent as ORM to connect to a database and Laravel will do a lot of magic to match your models and the tables in your database, pull out the columns, etc
In Spring Boot you build your models just by creating a class and then there are many ways to interact with the database.
- JDBC: it's APIs with drivers to connect and query a database, inlcuding raw queries
- JPA: it's a Java standard to follow to write ORM. Hibernate for example is then an actual ORM and an implementation of JPA
- Spring Data: it builds on top of ORMs like Hibernate providing extra stuff
For a very beginner I recommend Spring Data JDBC (which must be added as a dependency in Maven), it's the option with less abstractions and much easier for a beginner. As a Laravel dev you may have familiarity with MySQL, so consider adding the MySQL Driver in the dependencies. When you add dependencies in the maven's pom.xml
file your IDE will probably complain. You need to update your dependencies once you added them into the file, there should be a button (or just restart the IDE).
Then inform your application on how to connect to MySQL by adding these lines in the application.properties file:
spring.datasource.url=jdbc:mysql://localhost:3306/cats_app_database_name
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
In many tutorials you may hear about H2 Database. It's a very simple in memory SQL database with a web interface. If you can immediately use another database, like MySQL, Postgres or whatever, I think you are already in a much better position than if you were to use H2. Just know it exists.
Assuming a table messages
exists, the rawest way to now query the database is something like this:
@RestController
public class ExampleController {
private JdbcTemplate jdbcTemplate;
public ExampleController(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@GetMapping("hello")
public ResponseEntity<List<Map<String, Object>>> getHelloMessage() {
List<Map<String, Object>> messages = jdbcTemplate.queryForList("SELECT * FROM messages");
return ResponseEntity.ok(messages);
}
}
In this controller first we inject the jdbc client into the controller via its constructor public ExampleController(JdbcTemplate jdbcTemplate)
, then we perform the raw query and get back the results using jdbcTemplate.queryForList("SELECT * FROM messages");
By the way with List<Map<String, Object>>
I've been very explicit but you can actually just use var
if you feel like it, so you could end up doing something like var messages = jdbcTemplate.queryForList("SELECT * FROM messages");
Models
Spamming Object
and raw sql queries may not be not productive even for your short term beginner experiments so you may want a model and a better way to query the db. To create a model just create a class:
public class Cat {
Integer id;
String name;
String breed;
String ownerName;
}
you now have a Cat.java, it is already a model but you probably want to make it match with a table in your db.
Here is the thing. If you were using Spring Data JPA you would be able (but not required) to create the tables and the columns based on the model when the app first boots. I think it's premature as a beginner to follow this way and it's better to just create the tables yourself and then connect the model and the database manually.
To now have Cat
interact with a table in the database with the columns id, name, breed and owner_name you use @Table()
on top of the class, the @Id
annotation on the id and then @Column
on the other properties
// warning: no getters and setters defined
@Table("cats")
public class Cat {
@Id
Integer id;
@Column("name")
String name;
@Column("breed")
String breed;
@Column("owner_name")
String ownerName;
}
FYI we're being as explicit as possible in this article, using @Column
and @Table
be skipped in other cases.
Now that we have the Cat
model we use a repository to have a clean way to reach the table in the DB. We create an interface, we call it CatRepository and we make it extends CrudRepository
. With extending CrudRepository
we're using Spring Data JDBC and it will give us some methods to query the table later. We also need to add the @Repository
annotation so Spring will pick up the interface
@Repository
public interface CatRepository extends CrudRepository<Cat, Integer> {
}
The model and lombok
If you were to use the Cat
model as I've written it now you would not be able to get the data.
In Java having to define all getters and setters for properties is a given. The boilerplate code can be generated by your IDE or you can use lombok. Lombok is a dependency you can add and it gives you a set of annotations (like @AllArgsConstructor
, @Getter
, @Setter
) you can use on top of your class so that constructors, getters and setters are generated automatically for you. Having to learn yet another thing may feel cumbersome, but it's gonna require 10 minutes and it's great to speed up your beginner journey. Otherwise just use your IDE option to generate constructor, getters and setters.
Migrations
Flyway or Liquibase are the recommended way to manage migrations in Spring Boot and they are a beast on their own. There is a simple but not clean way to have migration by creating a schema.sql
and/or a data.sql
file in the resources folder and then adding spring.sql.init.mode=always
in the application.properties
file. This way every time the app is booted the two sql files will run. Of course by always running they can incur in an error and stop your application from booting, for example if you try to create a table that already exists without setting the proper SQL command for this case. So this options feels more useful as a pedagogical tool than anything more.
schema.sql
:
CREATE TABLE IF NOT EXISTS `cats` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`breed` VARCHAR(255) NOT NULL,
`owner_name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
);
Dependency injection with @Autowired vs constructor
When you need to inject a dependency into your class in Spring Boot you can either use @Autowired
or the constructor injection. For a beginner they have the same effect, for more expert users the there is a discussion on constructor injection vs @Autowired
and personally I also prefer using constructor injection in all cases.
Using @Autowired:
public class CatService { @Autowired private CatRepository catRepository; }
Constructor injection:
public class CatService { private final CatRepository catRepository;
public CatService(CatRepository catRepository) {
this.catRepository = catRepository;
}
}
(you may have noticed that I could not made the property final when using @Autowired)
Don't forget @Service
put the @Service
annotation on top of your service so that the class is picked up automatically by the framework and ready to be injected wherever you want, for example your controller:
@Service
public class CatService {
private final CatRepository catRepository;
public CatService(CatRepository catRepository) {
this.catRepository = catRepository;
}
public Iterable<Cat> getAllCats() {
return catRepository.findAll();
}
}
Rest Controller:
@RestController
public class CatController {
private final CatService catService;
public CatController(CatService catService) {
this.catService = catService;
}
@GetMapping("cats")
public ResponseEntity<Iterable<Cat>> getAllCats() {
return ResponseEntity.ok(catService.getAllCats());
}
}
Here's a few cats you can add on the fly in your db for testing purposes:
INSERT INTO `cats` (`name`, `breed`, `owner_name`) VALUES
('Whiskers', 'Maine Coon', 'Alice'),
('Mittens', 'Siamese', 'Bob'),
('Shadow', 'Persian', 'Charlie'),
('Luna', 'Bengal', 'Daisy');
More resources:
There are a lot of resources for Spring and Spring Boot out there but the following are the ones I wish I had at the start of the journey because they don't have any fluff, they practical and with the right level of detail.
Introductory Video
-
Peachez Programming - No BS Guide it truly is no BS. Being that you already are a dev you don't want to lose time having explained what a GET request and similar things are.
-
Marco Codes - Spring Boot tutorial crash course an even shorter but still useful introductory video tutorial, the channel also has other videos on Spring and Java that will be very useful as a beginner
Articles
- What is Spring Framework? An Unorthodox Guide, this article is the best introductory article I found, it goes into detail and it's very clear. Read this after you completed your first steps
Books
Use this book as a starting point: Spring Start Here: Learn what you need and learn it well by Laurentiu Spilca