Статьи

Качание с mongodb на весенней загрузке

Я фанат Spring Boot, и вот мой пример проекта mongodb по Spring Boot. Большинство примеров проектов mongodb настолько просты, что вы не будете далеко ходить за ними. Вы можете искать простые примеры Spring Data, но они могут быть намного сложнее, чем вы хотели бы. Так вот мой.
Вот пом, я буду использовать.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!--?xml version="1.0" encoding="UTF-8"?-->
    <modelversion>4.0.0</modelversion>
 
    <groupid>caught.co.nr</groupid>
    <artifactid>boottoymongodb</artifactid>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
 
 
    <!-- Inherit defaults from Spring Boot -->
    <parent>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-parent</artifactid>
        <version>1.0.0.BUILD-SNAPSHOT</version>
    </parent>
 
    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-data-mongodb</artifactid>
        </dependency>
 
    </dependencies>
 
    <!-- Needed for fat jar -->
    <build>
        <plugins>
            <plugin>
                <groupid>org.springframework.boot</groupid>
                <artifactid>spring-boot-maven-plugin</artifactid>
            </plugin>
        </plugins>
    </build>
 
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>http://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
 
    <pluginrepositories>
        <pluginrepository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/snapshot</url>
        </pluginrepository>
    </pluginrepositories>
</project>

Единственная нужная мне зависимость — это «spring-boot-starter-data-mongodb», которая содержит все необходимые зависимости для проекта весенней загрузки mongodb. Далее идет модель для моей коллекции. Аннотация к документу указывает на мою коллекцию под названием «продукты». Это необходимо, только если название вашей модели не соответствует названию вашей коллекции. Вы можете увидеть аннотацию поля, которая отображает имя поля в коллекции на имя поля модели.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@Document(collection = "products")
public class Product {
    @Id
    private String id;
    private String sku;
 
    @Field(value = "material_name")
    private String materialName;
 
    private Double price;
    private Integer availability;
 
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getSku() {
        return sku;
    }
 
    public void setSku(String sku) {
        this.sku = sku;
    }
 
    public String getMaterialName() {
        return materialName;
    }
 
    public void setMaterialName(String materialName) {
        this.materialName = materialName;
    }
 
    public Double getPrice() {
        return price;
    }
 
    public void setPrice(Double price) {
        this.price = price;
    }
 
    public Integer getAvailability() {
        return availability;
    }
 
    public void setAvailability(Integer availability) {
        this.availability = availability;
    }
 
    @Override
    public String toString() {
        return "Product{" +
                "id='" + id + '\'' +
                ", sku='" + sku + '\'' +
                ", materialName='" + materialName + '\'' +
                ", price=" + price +
                ", availability=" + availability +
                '}';
    }
}

Нам не понадобится слой DAO для манипулирования моими данными. MongoRepository — это интерфейс, который я должен реализовать, если я хочу использовать автоматически сгенерированные методы поиска в моем слое DAO, и я хочу этого. Каждое поле моей модели может быть запрошено с помощью этих автоматически сгенерированных методов. Для полного списка синтаксиса имени метода проверьте здесь . Мой запрос, приведенный ниже, возьмет имя sku, найдет в моей коллекции это имя и вернет соответствующие.

1
2
3
public interface ProductRepository extends MongoRepository < Product, String >{
    public List < Product > findBySku(String sku);
}

Теперь я представлю Сервис, который будет вызывать мой интерфейс DAO. Но подождите, я не реализовал этот интерфейс и написал необходимый код для загрузки моделей, верно? Да, эти методы генерируются автоматически, и мне не нужна реализация для этого интерфейса.

1
2
3
4
5
6
7
8
9
@Service
public class ProductService {
    @Autowired
    private ProductRepository repository;
 
    public List < Product > getSku(String sku){
        return repository.findBySku(sku);
    }
}

Далее, давайте запустим наш пример загрузки. Вот наш основной класс:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class BootMongoDB implements CommandLineRunner {
 
    @Autowired
    private ProductService productService;
 
    private static final Logger logger = LoggerFactory.getLogger(BootMongoDB.class);
 
    public void run(String... args) throws Exception {
        List < Product > sku = productService.getSku("NEX.6");
        logger.info("result of getSku is {}", sku);
    }
 
    public static void main(String[] args) throws Exception {
        SpringApplication.run(BootMongoDB.class, args);
    }
}

Если у вас есть соединение с экземпляром mongodb и пометкой, соответствующей названию, которое вы искали, в результате вы должны увидеть один или несколько Продуктов. То, что мы сделали, было довольно простым. Что делать, если я хочу более сложные запросы? Например, если я хочу определенный sku с доступностью, равной «1»? Я не могу сделать это без использования магии @Query. Поэтому я обновляю свой класс DAO.

1
2
3
4
5
6
public interface ProductRepository extends MongoRepository < Product, String >{
    public List < Product > findBySku(String sku);
 
    @Query(value = "{sku: ?0, availability : 1}")
    public List < Product > findBySkuOnlyAvailables(String sku);
}

Я предоставил прямой запрос для mongodb, где sku в сигнатуре моего метода будет вставлено в «? 0» в запросе и будет отправлено на mongodb. Вы можете обновить свой Сервис, а затем свой основной метод, чтобы увидеть, работает ли он. Вам может не понравиться написание запросов, которые не очень читабельны, если вы не очень хорошо знакомы с синтаксисом mongodb. Тогда это время для добавления пользовательских классов DAO. Невозможно добавлять и использовать методы, отличные от автоматически сгенерированных, в ProductRepository. Таким образом, мы добавим несколько классов и будем иметь отличные методы. Наш класс хранилища был назван «ProductRepository». Мы добавим новый интерфейс с именем «ProductRepositoryCustom» и новый метод, который найдет доступные skus для данного имени (двойник метода findBySkuOnlyAvailables).

1
2
3
public interface ProductRepositoryCustom {
    public List < Product > findBySkuOnlyAvailablesCustom(String sku);
}

Затем предоставьте реализацию для этого. Ниже вы видите, что мы внедряем mongotemplate ProductRepositoryCustom и делаем что-то с ним. Мы создаем два критерия. Первый для имени sku, а второй для доступности.

01
02
03
04
05
06
07
08
09
10
public class ProductRepositoryImpl implements ProductRepositoryCustom {
    @Autowired
    private MongoTemplate mongoTemplate;
 
    public List < Product > findBySkuOnlyAvailablesCustom(String sku) {
        Criteria criteria = Criteria.where("sku").is(sku).
andOperator(Criteria.where("availability").is(1));
        return mongoTemplate.find(Query.query(criteria), Product.class);
    }
}

Последний шаг для пользовательской реализации — обновление класса ProductRepository. Как вы можете видеть ниже, единственное обновление, которое мне нужно, это добавление моего ProductRepositoryCustom, чтобы мы могли связать их обоих вместе. Все эти названия могут звучать немного глупо. Но обратите внимание, что хотя имя вашего пользовательского интерфейса не имеет значения, изменение имени реализации приведет к генерации исключения:

1
Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property only found for type String! Traversed path: Product.sku.

Чтобы исправить это, убедитесь, что имя вашего класса реализации — «ProductRepositoryImpl», которое является объединением имени интерфейса, расширяющего MongoRepository и «Impl».

1
public interface ProductRepository extends MongoRepository < Product, String>, ProductRepositoryCustom

Если мы добавим наш новый метод в наш слой Service:

01
02
03
04
05
06
07
08
09
10
11
12
13
@Service
public class ProductService {
    @Autowired
    private ProductRepository repository;
 
    public List < Product > getSku(String sku){
        return repository.findBySku(sku);
    }
 
    public List < Product > getAvailableSkuCustom(String sku){
        return repository.findBySkuOnlyAvailablesCustom(sku);
    }
}

Затем обновите метод run нашего основного класса:

1
2
3
4
5
6
7
public void run(String... args) throws Exception {
        List < Product > sku = productService.getSku("NEX.6");
        logger.info("result of getSku is {}", sku);
 
        List < Product > availableSkuCustom = productService.getAvailableSkuCustom("NEX.6");
        logger.info("result of availableSkuCustom is {}", availableSkuCustom);
    }

Опять вы должны увидеть что-то в журнале! Вы можете проверить весь проект на GitHub .