Issue
I'm learning Spring but I don't understand where I have to fill my structure... for example, I want a list of Teams where each team have a list of players.
This is the code, i have my TeamApplication:
@SpringBootApplication
public class TeamApplication {
public static void main(String[] args) {
SpringApplication.run(TeamApplication.class, args);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Team team = context.getBean(Team.class);
Player player = context.getBean(Player.class);
}
}
then I have AppConfig:
@Configuration
public class AppConfig {
@Bean
public Team team() {
return new Team();
}
@Bean
public Player player() {
return new Player();
}
}
so Player is:
public class Player {
private static final Logger LOG = LoggerFactory.getLogger(Player.class);
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@PostConstruct
public void init() {
LOG.info("Player PostConstruct");
}
@PreDestroy
public void destroy() {
LOG.info("Player PreDestroy");
}
}
and Team is:
public class Team {
private static final Logger LOG = LoggerFactory.getLogger(Team.class);
private String name;
private List<Player> listPlayer;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Player> getListPlayer() {
return listPlayer;
}
public void setListPlayer(List<Player> listPlayer) {
this.listPlayer = listPlayer;
}
@PostConstruct
public void init() {
LOG.info("Team PostConstruct");
}
@PreDestroy
public void destroy() {
LOG.info("Team PreDestroy");
}
}
Now: - Where I have to fill those lists? in PostConstruct? But in this way i have always the same datas... in an simple Java application I first create players:
Player p1 = new Player();
p1.setName("A");
p1.setAge(20);
Player p2 = new Player();
p1.setName("B");
p1.setAge(21);
Player p3 = new Player();
p1.setName("C");
p1.setAge(22);
Then I create my teams:
List<Person> l1 = new LinkedList<>();
l1.add(p1);
l1.add(p2);
Team t1 = new Team();
t1.setListPlayer(l1);
List<Person> l2 = new LinkedList<>();
l2.add(p3);
Team t2 = new Team();
t1.setListPlayer(l2);
so... in Spring:
- Where can I init my players (in PostConstruct I will get always the same name/age)?
- Where have I to create my listTeam? After getBean in TeamApplication?
Kind regards!
Solution
I've created a quick example project on GitHub. I need to emphasize that this is not a production ready code and you shouldn't follow it's patterns for I did't refactor it to be pretty but understandable and simple instead.
First you don't have to define the set of teams and players. As you said the data will be loaded from DB, so let the users do this work. :) Instead, you need to define the services (as spring beans) which contain the business logic for the users to do their task.
How does Spring know my db table structure and the DB table <-> Java object mapping? If you want to persist your teams and players some DB, you should mark them with annotations for Spring. In the example project I put the @Entity
annotation to them so Spring will know it has to store them. Spring use convention over configuration so if I don't define any db table names, Spring will generate some from the entity class names, in this case PLAYER
, TEAM
and TEAM_PLAYERS
. Also I annotated the Java class field I wanted to store with the following annotations:
@Column
: this field will be stored in a DB column. Without any further config Spring will generate the name of it's column.@Id
and@GeneratedValue
: Spring will auto generate the id of the persisted entities and store it's value in this annotated field.@OneToMany
: this annotation tells Spring to create a relation between two entities. Spring will create theTEAM_PLAYERS
join table because of this annotation, and store the team-player id pairs in it.
How does Spring know the database's URL? As I imported H2 db in maven's pom.xml Spring will use it, and without any configuration it'll store data in memory (which will lost between app restarts). If you look at the application.yaml you can find the configuration for the DB, and Spring'll do the same. If you uncomment the commented lines Spring'll store your data under your home directory.
How does Spring sync these entities to the DB? I've created two repositories and Spring'll use them to save, delete and find data. They're interfaces (PlayerRepository
and TeamRepository
) and they extend CrudRepository interface which gives them some basic CRUD operations without any further work.
So far so good, but how can the users use these services? I've published these functionalities through HTTP endpoints (PlayerController
and TeamController
). I marked them as @RestController
s, so spring will map some HTTP queries to them. Through them users can create, delete, find players and teams, and assign players to teams or remove one player from a team.
You can try this example if you build and start it with maven, and send some queries to these endpoints by curl or by navigating to http://localhost:8080/swagger-ui.html page.
I've done some more configuration for this project but those are not relevant from the aspect of your question. I haven't explained the project deeper but you can make some investigation about my solutions and you can find documentations on Spring's site.
Conclusion:
My Spring managed classes are:
@Entity
:Player
,Team
Repository
:PlayerRepository
,TeamRepository
@RestController
:PlayerController
,TeamController
The flow of a call:
User
-(HTTP)->@RestController
->Repository(Entity)
->DB
Answered By - Szilárd Fodor