স্প্রিং বুট - প্রাথমিক ডেটা লোড হচ্ছে


179

আমি ভাবছি অ্যাপ্লিকেশন শুরু হওয়ার আগে প্রাথমিক ডাটাবেস ডেটা লোড করার সর্বোত্তম উপায় কোনটি? আমি যা খুঁজছি তা এমন একটি যা আমার এইচ 2 ডাটাবেসের সাথে ডেটা পূরণ করবে।

উদাহরণস্বরূপ, আমার কাছে একটি ডোমেন মডেল রয়েছে "ব্যবহারকারী" আমি ব্যবহারকারী / ব্যবহারকারীদের কাছে গিয়ে ব্যবহারকারীদের অ্যাক্সেস করতে পারি তবে প্রাথমিকভাবে ডাটাবেসে কোনও ব্যবহারকারী থাকতে পারে না তাই আমাকে সেগুলি তৈরি করতে হবে। ডাটাবেস স্বয়ংক্রিয়ভাবে পূরণ করার জন্য কি আছে?

এই মুহুর্তে আমার কাছে একটি বিন রয়েছে যা ধারকটি দ্বারা তাত্ক্ষণিকভাবে আসে এবং আমার জন্য ব্যবহারকারী তৈরি করে।

উদাহরণ:

@Component
public class DataLoader {

    private UserRepository userRepository;

    @Autowired
    public DataLoader(UserRepository userRepository) {
        this.userRepository = userRepository;
        LoadUsers();
    }

    private void LoadUsers() {
        userRepository.save(new User("lala", "lala", "lala"));
    }
}

তবে আমি খুব সন্দেহ করি যে এটি করার সর্বোত্তম উপায়। অথবা এটা?


4
এটি কাজ করবে, বা কেবল ডেটা যোগ করতে data.sqlএবং / অথবা schema.sqlসূচনা ডেটাতে .. এই সমস্ত তথ্যসূত্র গাইডে নথিবদ্ধ করা আছে (যা আমি পড়ার পরামর্শ দিই)।
এম। ডিনুম

যদি এটি আপনাকে সহায়তা করে তবে সঠিক উত্তরটি চিহ্নিত করুন।
পুনর্বার জন্ম

কেউ কি এই কাজ করতে পেয়েছেন? আমি এখনও এটি একসাথে রাখতে অক্ষম এবং এখানে আমি কী অনুপস্থিত তা নিশ্চিত করতে পারছি না। git.io/v5SWx
শ্রীনি

উত্তর:


294

আপনি সহজেই আপনার এসসিআর / প্রধান / সংস্থান ফোল্ডারে একটি ডেটা.এসকিউএল ফাইল তৈরি করতে পারেন এবং এটি স্বয়ংক্রিয়ভাবে স্টার্টআপে কার্যকর করা হবে। এই ফাইলটিতে আপনি কিছু সন্নিবেশ বিবৃতি যুক্ত করুন, যেমন:

INSERT INTO users (username, firstname, lastname) VALUES
  ('lala', 'lala', 'lala'),
  ('lolo', 'lolo', 'lolo');

একইভাবে, আপনি নিজের স্কিমা তৈরি করতে স্কিমা.এসকিএল ফাইল (বা স্কিমা-এইচ 2.এসকিএল) তৈরি করতে পারেন:

CREATE TABLE task (
  id          INTEGER PRIMARY KEY,
  description VARCHAR(64) NOT NULL,
  completed   BIT NOT NULL);

যদিও সাধারণত আপনার এটি করা উচিত নয় যেহেতু স্প্রিং বুট ইতিমধ্যে হাইবারনেটকে মেমরি ডেটাবেস-এর জন্য আপনার সত্তার উপর ভিত্তি করে আপনার স্কিমা তৈরি করতে হাইবারনেট কনফিগার করে। আপনি যদি সত্যিই স্কিমা.এসকিউএল ব্যবহার করতে চান তবে আপনাকে এই অ্যাপ্লিকেশনটিতে যোগ করে এই বৈশিষ্ট্যটি অক্ষম করতে হবে rop

spring.jpa.hibernate.ddl-auto=none

ডাটাবেস সূচনা সম্পর্কে ডকুমেন্টেশনে আরও তথ্য পাওয়া যাবে ।


আপনি যদি স্প্রিং বুট 2 ব্যবহার করেন তবে ডাটাবেস সূচনা কেবল এম্বেড করা ডাটাবেসের জন্য কাজ করে (এইচ 2, এইচএসকিউএলডিবি ...)। আপনি যদি এটি অন্যান্য ডাটাবেসের জন্যও ব্যবহার করতে চান তবে আপনার spring.datasource.initialization-modeসম্পত্তিটি পরিবর্তন করতে হবে :

spring.datasource.initialization-mode=always

আপনি যদি একাধিক ডাটাবেস বিক্রেতাদের ব্যবহার করছেন তবে আপনি কোন ডাটাবেস প্ল্যাটফর্মটি ব্যবহার করতে চান তার উপর নির্ভর করে আপনি আপনার ফাইলের নাম-h2.sql বা ডেটা-মাইএসকিএল.এসকিএল করতে পারেন।

সেই কাজটি করতে, আপনাকে spring.datasource.platformসম্পত্তিটি কনফিগার করতে হবে যদিও:

spring.datasource.platform=h2

ধন্যবাদ আপনাকে @ g00glen00b সাফ করার জন্য: "এবং এটি স্বয়ংক্রিয়ভাবে শুরু করার সময় কার্যকর করা হবে"। অ্যাডস্ক্রিপ্ট (গুলি) বিকল্পটি ব্যবহার করে আমার বিনের কনফিগারেশনে ডেটা.এসকিউএল ফাইলটি অন্তর্ভুক্ত করার সাথে সাথে আমি ত্রুটিগুলি পাচ্ছিলাম। এই মুহুর্তে স্কিমাটি এখনও নির্মিত হয়নি।
বেনজামিন স্ল্যাববার্ট

5
@nespapu আপনি এটা ভুল যদিও, আছে schema.sql/ data.sqlফাইল যখন মৃত্যুদন্ড কার্যকর করা হবে spring.datasource.initializeহয় true(যা ডিফল্ট)। spring.jpa.hibernate.ddl-autoএসকিউএল ফাইল ব্যবহার না করে আপনার সত্তার কনফিগারেশনের উপর ভিত্তি করে আপনার টেবিলগুলি তৈরি করতে ব্যবহার করা যেতে পারে। এটি মেমরির ডাটাবেসে ডিফল্টরূপে সক্ষম হয়। এজন্য আমি আমার উত্তরে নোটটি যুক্ত করে ব্যাখ্যা করেছিলাম যে আপনি যদি মেমরির একটি ডাটাবেস ব্যবহার করেন এবং আপনি এটি ব্যবহার করতে চান তবে schema.sqlআপনাকে অক্ষম করা দরকার spring.jpa.hibernate.ddl-autoঅন্যথায় উভয়ই আপনার টেবিলটি তৈরি করার চেষ্টা করবে।
g00glen00b

7
আপনি যদি data-h2.sqlআপনার প্রাথমিক ডেটার জন্য ফাইলের নামটি ব্যবহার করতে চান তবে spring.datasource.platform=h2আপনার অ্যাপ্লিকেশন বৈশিষ্ট্যগুলিতেও সেট করা উচিত ।
জেসন ইভান্স

1
প্রতিটি সময় বসন্ত-বুট অ্যাপ্লিকেশনটি চালিত হওয়ার সাথে সাথে ডেটা.এসকিউএল ফাইলটি কার্যকর করা হয়। এর অর্থ হ'ল যদি আপনার কাছে বিবৃতি org.h2.jdbc.JdbcSQLExceptionsertোকানো হয় তবে এগুলি একটি এক্সসেপশন হতে পারে , কারণ ডেটাবেজে ডেটা ইতিমধ্যে উপস্থিত রয়েছে। আমি একটি এম্বেডড এইচ 2 ডাটাবেস ব্যবহার করছি, তবে সমস্যাটি একই থাকে।
ইগোর

1
@ g00glen00b দুঃখজনকভাবে এগুলি সবই সহজ তবে কারণ এইচ 2 ডাটাবেসের ক্ষেত্রে সমস্যা রয়েছে MERGE INTO। আমি বুঝতে পেরেছি যে এখানে একটি ডাটা.সিকিএল এর পরিবর্তে আমদানি.এসকিউএল ফাইল ব্যবহার করে এটিকে রোধ করার উপায় রয়েছে । এটি প্রয়োজন spring.jpa.hibernate.ddl-autoথেকে তৈরি বা তৈরি ড্রপ । তারপরেই যখনই স্কিমা ফাইল তৈরি হয় (এবং / অথবা একটি স্কিমা.এসকিউএল চালানো হয়), আমদানি.এসকিউএলও কার্যকর করা হয়। তবুও: এটিকে অনুক্রমের মতো মনে হয় এবং থিম ডেটা তৈরির কোনও পরিষ্কার বাস্তবায়ন নয়।
ইগোর

82

আমি যদি কেবল সাধারণ পরীক্ষার ডেটা sertোকাতে চাই তবে আমি প্রায়শই একটি প্রয়োগ করি ApplicationRunner। এই ইন্টারফেসের প্রয়োগগুলি অ্যাপ্লিকেশন প্রারম্ভকালে চালানো হয় এবং কিছু পরীক্ষার ডেটা .োকাতে উদাহরণস্বরূপ একটি স্বতঃরেচিত সংগ্রহস্থল ব্যবহার করতে পারে।

আমি মনে করি এ জাতীয় বাস্তবায়ন আপনার চেয়ে কিছুটা স্পষ্ট হবে কারণ ইন্টারফেস থেকে বোঝা যাচ্ছে যে আপনার প্রয়োগটি প্রস্তুত হওয়ার পরে সরাসরি আপনি করতে চান এমন কিছু রয়েছে।

আপনার বাস্তবায়ন sth দেখাবে। এটার মত:

@Component
public class DataLoader implements ApplicationRunner {

    private UserRepository userRepository;

    @Autowired
    public DataLoader(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void run(ApplicationArguments args) {
        userRepository.save(new User("lala", "lala", "lala"));
    }
}

32

পরামর্শ হিসাবে চেষ্টা করুন:

@Bean
public CommandLineRunner loadData(CustomerRepository repository) {
    return (args) -> {
        // save a couple of customers
        repository.save(new Customer("Jack", "Bauer"));
        repository.save(new Customer("Chloe", "O'Brian"));
        repository.save(new Customer("Kim", "Bauer"));
        repository.save(new Customer("David", "Palmer"));
        repository.save(new Customer("Michelle", "Dessler"));

        // fetch all customers
        log.info("Customers found with findAll():");
        log.info("-------------------------------");
        for (Customer customer : repository.findAll()) {
            log.info(customer.toString());
        }
        log.info("");

        // fetch an individual customer by ID
        Customer customer = repository.findOne(1L);
        log.info("Customer found with findOne(1L):");
        log.info("--------------------------------");
        log.info(customer.toString());
        log.info("");

        // fetch customers by last name
        log.info("Customer found with findByLastNameStartsWithIgnoreCase('Bauer'):");
        log.info("--------------------------------------------");
        for (Customer bauer : repository
                .findByLastNameStartsWithIgnoreCase("Bauer")) {
            log.info(bauer.toString());
        }
        log.info("");
    }
}

বিকল্প 2: স্কিমা এবং ডেটা স্ক্রিপ্টগুলির সাহায্যে সূচনা করুন

পূর্বশর্ত: application.propertiesআপনাকে এটি উল্লেখ করতে হবে:

spring.jpa.hibernate.ddl-auto=none(অন্যথায় স্ক্রিপ্টগুলি হাইবারনেট দ্বারা উপেক্ষা করা হবে, এবং এটি @Entityএবং / অথবা @Tableএনोटোটেড শ্রেণীর জন্য প্রকল্প স্ক্যান করবে )

তারপরে, আপনার MyApplicationক্লাসে এটি পেস্ট করুন:

@Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("org.h2.Driver");
    dataSource.setUrl("jdbc:h2:~/myDB;MV_STORE=false");
    dataSource.setUsername("sa");
    dataSource.setPassword("");

    // schema init
    Resource initSchema = new ClassPathResource("scripts/schema-h2.sql");
    Resource initData = new ClassPathResource("scripts/data-h2.sql");
    DatabasePopulator databasePopulator = new ResourceDatabasePopulator(initSchema, initData);
    DatabasePopulatorUtils.execute(databasePopulator, dataSource);

    return dataSource;
}

scriptsফোল্ডার যেখানে ফোল্ডারের অধীনে অবস্থিত resources(IntelliJ আইডিয়া)

আশা করি এটি কাউকে সাহায্য করবে


3
বিকল্প 2 দুর্দান্ত কারণ এটি কী ঘটছে তার সুস্পষ্ট প্রমাণ দেয়। একাধিক ডেটাসোর্সগুলির সাথে বিশেষত স্প্রিংয়ের ডেটাসোর্সআউটো কনফিগারেশন.ক্লাসটি অক্ষম করা প্রয়োজন হতে পারে যেখানে এখানে প্রদত্ত অন্যান্য সমস্ত ডেটা.এসকিএল এবং স্কিমা.এসকিউএল সমাধান কাজ করা বন্ধ করে দেয়।
কাইকারনো

1
আপনি যদি প্রাথমিক ডেটা লোড করতে চান তবে এখনও হাইবারনেটটি ডিডিএল তৈরি করতে চান তবে আপনার কাছে একাধিক ডাটাসোর্স রয়েছে এবং সেগুলি ম্যানুয়ালি সেট আপ করা যায়, তবে এই ক্ষেত্রে আরও ভাল বিকল্পটি স্ট্রোকভারফ্লো.com / a / 23036217 / 3092830 অনুসারে স্প্রিংয়ের ডেটাসোর্সআইনিটাইজার বিট ঘোষণা করা is যেহেতু এটি আপনার জন্য @ পোষ্টকনস্ট্রাক্ট ইস্যুটি নেবে।
কাইকারনো

32

আপনি চালাতে চান এমন sql ফাইলগুলির তালিকাতে আপনি একটি spring.datasource.dataসম্পত্তি যুক্ত application.propertiesকরতে পারেন। এটার মত:

spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql

এরপরে এই ফাইলগুলির প্রত্যেকটিতে স্ক্যালের সন্নিবেশ বিবৃতিগুলি চালিত হবে, আপনাকে জিনিসগুলি পরিষ্কার রাখার অনুমতি দেয়।

আপনি ক্লাসপথে ফাইলগুলি রাখলে উদাহরণস্বরূপ src/main/resourcesসেগুলি প্রয়োগ করা হবে। বা প্রতিস্থাপন classpath:সঙ্গে file:এবং ফাইল একটি সুনির্দিষ্ট পাথ ব্যবহার


5
আপনি যদি একটি বাহ্যিক ফাইল চান তবে file:পরিবর্তে রাখতে ভুলবেন না classpath:
আলেকসান্দার লেচ

ফাইলগুলি (অ্যাকাউন্টস.এসকিউএল, ...) কোথায় থাকবে?
dpelisek

1
@dpelisek src / main / উত্সগুলি কাজ করা উচিত। উত্তর আপডেট হয়েছে।
রোবজিল্কিন্স

14

আপনি এর মতো কিছু ব্যবহার করতে পারেন:

@SpringBootApplication  
public class Application {

@Autowired
private UserRepository userRepository;

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

@Bean
InitializingBean sendDatabase() {
    return () -> {
        userRepository.save(new User("John"));
        userRepository.save(new User("Rambo"));
      };
   }
}

11

স্প্রিং বুট আপনাকে স্প্রিং ব্যাচ ব্যবহার করে আপনার ডাটাবেস সূচনা করতে একটি সাধারণ স্ক্রিপ্ট ব্যবহার করতে দেয় ।

তবুও, আপনি যদি ডিবি সংস্করণগুলি পরিচালনা করতে আরও কিছু বিশদভাবে কিছু ব্যবহার করতে চান তবে স্প্রিং বুট ফ্লাইওয়ের সাথে ভালভাবে সংহত করে ।

আরো দেখুন:


6
এখানে বসন্ত ব্যাচের পরামর্শ দেওয়া ওভারকিল বলে মনে হচ্ছে।
নিক

@ নিক, ওপি তথ্যের পরিমাণ উল্লেখ করে না .. যাইহোক উত্তরটি বসন্তের ব্যাচ সম্পর্কে নয়।
এক্সট্রিম বাইকার

আমার মতে, ফ্লাইওয়ে বা লিকুইবেস হ'ল সঠিক উপায়। নিকের মন্তব্য সম্পর্কে এবং / এসসিআর / মেইন / রিসোর্সগুলির উন্নতি সম্পর্কে আরও কিছু সম্পর্কে নিশ্চিত নন। হ্যাঁ, আধুনিকগুলি ছোট প্রকল্পগুলির জন্য কাজ করবে। এক্স্ট্রিম বাইকারের উত্তর খুব ছোট পরিশ্রমের মাধ্যমে আরও অনেক কার্যকারিতা দেয়।
আলেকজান্দ্রোস

10

স্প্রিং বুট 2 ডেটা। এসকিউএল আমার সাথে বসন্ত বুট 1.5 এর মতো কাজ করছিল না

import.sql

এছাড়াও import.sqlহাইবারনেট স্ক্র্যাচ থেকে স্কিমা তৈরি করে (অর্থাৎ, ডিডিএল-অটো সম্পত্তি তৈরি বা তৈরি-ড্রপ সেট করা থাকলে) ক্লাসপথের মূলের নামের একটি ফাইল প্রারম্ভকালে কার্যকর করা হয়।

খুব গুরুত্বপূর্ণ দ্রষ্টব্য আপনি কী সন্নিবেশ করালে কীগুলি অনুলিপি করা যাবে না ডিডিএল-অটো সম্পত্তি ব্যবহার করবেন না আপডেট করার জন্য সেট করা হয়েছে কারণ প্রতিটি পুনঃসূচনা দিয়ে আবার একই ডেটা sertোকানো হবে

আরও তথ্যের জন্য আপনি বসন্তের ওয়েবসাইটটি পরীক্ষা করে দেখুন

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html


স্প্রিং 2-এ ডাটাবেস সূচনা কেবল এম্বেড করা ডাটাবেসের জন্য কাজ করে যদি আপনি অন্যান্য ডাটাবেসের জন্য এটি ব্যবহার করতে চান তবে আপনাকে স্প্রিং.ড্যাটাসোর্স.ইনটিয়লাইজেশন-মোড = সর্বদা নির্দিষ্ট করতে হবে
এডু কোস্টা

6

আমি যেভাবে পেয়েছি তা এখানে:

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

    /**
     * This event is executed as late as conceivably possible to indicate that
     * the application is ready to service requests.
     */

    @Autowired
    private MovieRepositoryImpl movieRepository;

    @Override
    public void onApplicationEvent(final ApplicationReadyEvent event) {
        seedData();
    }

    private void seedData() {
        movieRepository.save(new Movie("Example"));

        // ... add more code
    }

}

এই নিবন্ধটির লেখককে ধন্যবাদ:

http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/


আপনি পরিষেবাটি ব্যবহার করছেন এবং যদি স্বত্বাধিকারী ভাণ্ডারগুলিতে পরিষেবা ব্যবহার করা হয় তবে এটি কাজ করে না
সাইলেন্টসো


4

আমি একইভাবে সমস্যাটি সমাধান করেছি:

@Component
public class DataLoader {

    @Autowired
    private UserRepository userRepository;

    //method invoked during the startup
    @PostConstruct
    public void loadData() {
        userRepository.save(new User("user"));
    }

    //method invoked during the shutdown
    @PreDestroy
    public void removeData() {
        userRepository.deleteAll();
    }
}

1

যদি কেউ গ্রহণযোগ্য উত্তর অনুসরণ করেও এটি কাজ করতে লড়াই করে চলেছে তবে আমার জন্য কেবল আমার src/test/resources/application.ymlএইচ 2 datasourceবিবরণ যুক্ত করে কাজ করুন:

spring:
  datasource:
    platform: h2
    url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
    driver-class-name: org.h2.Driver
    username: sa
    password:

1

নীচের মত এটি অর্জনের জন্য আপনি নিবন্ধন করতে এবং ইভেন্ট শ্রোতাদের করতে পারেন:

@EventListener
public void seed(ContextRefreshedEvent event) {
    userRepository.save(new User("lala", "lala", "lala"));
}

যখন কনটেক্সটরিফ্রেসইভেন্টটি বরখাস্ত করা হয়, তখন আমরা অ্যাপ্লিকেশনটিতে সমস্ত স্বায়িত শিমের অ্যাক্সেস পাই - মডেল এবং সংগ্রহশালা সহ।


1

আপনি যদি কেবল কয়েকটি সারি সন্নিবেশ করতে চান এবং আপনার কাছে জেপিএ সেটআপ রয়েছে। আপনি নীচে ব্যবহার করতে পারেন

    @SpringBootApplication
        @Slf4j
        public class HospitalManagementApplication {

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

            @Bean
            ApplicationRunner init(PatientRepository repository) {
                return (ApplicationArguments args) ->  dataSetup(repository);
            } 

            public void dataSetup(PatientRepository repository){
            //inserts

     }

1
আমি এই দীর্ঘ ফিরে ব্যবহার করছিলাম, মনে করতে সক্ষম ছিল না। এই হল. ধন্যবাদ।
ফ্রিল্যান্সার


0

সর্বাধিক কমপ্যাক্ট (ডায়নামিক ডেটার জন্য) @ ম্যাথিয়াস-ডিপঙ্ক্ট সলিউশন মেইন অ্যাপে (লোমবকের সাথে @AllArgsConstructor) রাখুন:

@SpringBootApplication
@AllArgsConstructor
public class RestaurantVotingApplication implements ApplicationRunner {
  private final VoteRepository voteRepository;
  private final UserRepository userRepository;

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

  @Override
  public void run(ApplicationArguments args) {
    voteRepository.save(new Vote(userRepository.getOne(1), LocalDate.now(), LocalTime.now()));
  }
}

0

আপনি বেশিরভাগ ওখানেই থাকেন!

@Component
public class DataLoader implements CommandLineRunner {

    private UserRepository userRepository;

    public DataLoader(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void run(String... args) throws Exception {
         LoadUsers()
    }

    private void LoadUsers() {
        userRepository.save(new User("lala", "lala", "lala"));
    }
}

0

আপনি নীচের কোড ব্যবহার করতে পারেন। নিম্নলিখিত কোডে একটি ডাটাবেস সন্নিবেশ বসন্ত বুট অ্যাপ্লিকেশন শুরু করার সময় ঘটে।

@SpringBootApplication
public class Application implements CommandLineRunner {
    
    @Autowired
    private IService<Car> service;

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

    @Override
    public void run(String... args) throws Exception {
        for(int i=1; i<=1000; i++) {
            Car car = new Car();
            car.setName("Car Name "+i);
            book.setPrice(50 + i);
            service.saveOrUpdate(car);
        }
    }

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.