Java Spring Boot - 如何像在 PHP Laravel 中一样为数据库提供种子

Ale*_*lex 6 php java spring spring-boot

我正在尝试学习 Java Spring Boot。我来自 PHP Laravel,我怀念这个框架的一件事是制作数据库播种器和工厂等是多么容易。我正在尝试找出一种方法来播种我的 h2 数据库,这样每次应用程序进行热重载,它将创建一些用于测试的数据。到目前为止,在 SpringBootApplication 文件中我有这个

    @Bean
    CommandLineRunner commandLineRunner(){
        return args -> {
            Faker faker = new Faker(new Locale("en-US"));
            Employee emp1 = new Employee(faker.name().firstName(), faker.name().lastName(), faker.internet().safeEmailAddress());
            Employee emp2 = new Employee(faker.name().firstName(), faker.name().lastName(), faker.internet().safeEmailAddress());
            Employee emp3 = new Employee(faker.name().firstName(), faker.name().lastName(), faker.internet().safeEmailAddress());
            Employee emp4 = new Employee(faker.name().firstName(), faker.name().lastName(), faker.internet().safeEmailAddress());
            Employee emp5 = new Employee(faker.name().firstName(), faker.name().lastName(), faker.internet().safeEmailAddress());
            Project proj1 = new Project(faker.app().name(), faker.app().version() ,faker.lorem().sentence());
            Project proj2 = new Project(faker.app().name(), faker.app().version() ,faker.lorem().sentence());
            Project proj3 = new Project(faker.app().name(), faker.app().version() ,faker.lorem().sentence());

            proj1.addEmployee(emp1);
            proj2.addEmployee(emp2);
            proj3.addEmployee(emp4);
            proj3.addEmployee(emp3);
            proj3.addEmployee(emp1);
            proj3.addEmployee(emp4);
            proj3.addEmployee(emp5);

            emp1.setProjects(Arrays.asList(proj1, proj2, proj3));
            emp2.setProjects(Arrays.asList(proj1));
            emp3.setProjects(Arrays.asList(proj2));
            emp4.setProjects(Arrays.asList(proj3));
            emp5.setProjects(Arrays.asList(proj3));
            employeeRepository.save(emp1);
            employeeRepository.save(emp2);
            employeeRepository.save(emp3);
            employeeRepository.save(emp4);
            employeeRepository.save(emp5);
            projectRepository.save(proj1);
            projectRepository.save(proj2);
            projectRepository.save(proj3);
        };
    }
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,它都是硬编码的,但我想知道是否有更好的方法来做到这一点。

例如,我想到了这样的事情:

    @Bean
    CommandLineRunner commandLineRunner(){
        return args -> {
            int min = 0, max = 1000, rand = 0;
            Faker faker = new Faker(new Locale("en-US"));
            Employee[] emp = new Employee[max];
            Project[] proj = new Project[max];
// Employee and Project are entities and I wanted to be able to iterate and 
// have the object get incremented so it would be like emp1, emp2, emp3 etc. 
            for(int i = 0; i < max; i++)
            {
                emp[i] = new Employee(faker.name().firstName(), faker.name().lastName(), faker.internet().safeEmailAddress());
                proj[i] = new Project(faker.app().name(), faker.app().version() ,faker.lorem().sentence());
            }
            Random random = new Random();
// here I'm trying to randomly pick from a range of numbers of the previous 
// created objects just to make it seem more organic
            for(int j = 0; j < max; j++)
            {
                rand = random.nextInt((max - min) + 1) + min;
                proj[j].setEmployees(Arrays.asList(emp[rand]));
                emp[j].setProjects(Arrays.asList(proj[rand]));
                employeeRepository.save(emp[rand]);
                projectRepository.save(proj[rand]);
            }
        };
Run Code Online (Sandbox Code Playgroud)

上面的确实不起作用。我想知道是否有人知道更好的解决方案。我什至不确定这是否是我应该播种数据库的地方,或者在架构/设计方面是否有更好的选择。例如,如果我需要使用用户在应用程序中可能具有的不同角色等内容来为数据库添加种子,该怎么办?

例如,在 Laravel 中,我可以做这样的事情作为连接表(希望这能更多地说明这一点):

foreach($projects as $project)
            foreach($employees as $employee)
                Project_Employee::create([
                    'created_at' => Carbon::now(),
                    'updated_at'  => Carbon::now(),
                    'employee_id' => $employee->id,
                    'project_id' => $project->id,
                ]);
Run Code Online (Sandbox Code Playgroud)

感谢对此的任何帮助,谢谢。

编辑:我终于得到了一些工作,但我遇到了另一个问题,它创建空行并且始终位于同一位置,我不确定为什么。这两个地图都没有任何空数据。我不确定我在这里做错了什么,谢谢你的帮助。

这是我的代码:

    @Bean
    CommandLineRunner commandLineRunner(){
        return args -> {
            int min = 0, max = 10, rand = 0;
            Faker faker = new Faker(new Locale("en-US"));
            HashMap<Integer, Employee> mapEmployees = new HashMap<>();
            HashMap<Integer, Project> mapProjects = new HashMap<>();
            Random random = new Random();
            Employee employee = new Employee();
            Project project = new Project();

            for(int i = 0; i < max; i++)
            {
                mapEmployees.put(i, new Employee(faker.name().firstName(), faker.name().lastName(), faker.internet().safeEmailAddress()));
                mapProjects.put(i, new Project(faker.app().name(), faker.app().version() ,faker.lorem().sentence()));
            }
            for(int j = 0; j < max; j++)
            {
                rand = random.nextInt((max - min)) + min;
                project.setEmployees(Collections.singletonList(mapEmployees.get(rand)));
                employee.setProjects(Collections.singletonList(mapProjects.get(rand)));
                employeeRepository.save(employee);
                projectRepository.save(project);
            }
        };
Run Code Online (Sandbox Code Playgroud)

另一个奇怪的事情是有时行数会减少。每次应该是 10 行,但由于某种原因可能会减少 1 行

在此输入图像描述

上述结果中有 9 行。

在此输入图像描述

上述结果中有 10 行。

Ale*_*lex 3

弄清楚了。问题在于使用 aList<T>并在循环之外拥有每个实体的新实例的 set 方法。一旦我把它放进去,一切就都正常了。我唯一无法完成的事情是随机性部分,但数据就在那里,这就是本次练习的重点。我希望这对尝试做类似事情的其他人有所帮助。另请查看此解决方案,用于制作数据库播种器类如何在 Spring Boot 项目中播种数据库?

@SpringBootApplication
public class WebApp {

    @Autowired
    EmployeeRepository employeeRepository;
    @Autowired
    ProjectRepository projectRepository;

    public static void main(String[] args) {
        SpringApplication.run(ProjectManagementApplication.class, args);
    }

    @Bean
    CommandLineRunner commandLineRunner(){
        return args -> {
            int max = 10;
            Faker faker = new Faker(new Locale("en-US"));
            HashMap<Integer, Employee> mapEmployees = new HashMap<>();
            HashMap<Integer, Project> mapProjects = new HashMap<>();

            for(int i = 0; i < max; i++)
            {
                Employee employee = new Employee(faker.name().firstName(), faker.name().lastName(), faker.internet().safeEmailAddress());
                Project project = new Project(faker.app().name(), faker.app().version() ,faker.lorem().sentence());
                mapEmployees.put(i, employee);
                mapProjects.put(i, project);
                employee.setProjects(Collections.singletonList(mapProjects.get(i)));
                project.setEmployees(Collections.singletonList(mapEmployees.get(i)));
                projectRepository.save(project);
                employeeRepository.save(employee);
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)