Hướng dẫn spring mongodb enum mapping - bản đồ mùa xuân mongodb enum

Tôi muốn mã không ném ngoại lệ khi tải mã Java giá trị từ Mongo không tồn tại trong mã Enum

Mẫu mực:

java.lang.IllegalArgumentException: No enum constant fr.myapp.type.OrderOptionEnum.TELEPHONE
at java.lang.Enum.valueOf(Enum.java:238)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleRead(MappingMongoConverter.java:819)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readCollectionOrArray(MappingMongoConverter.java:909)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1184)

Vì điện thoại không tồn tại ở OrderOptionEnum

Tôi chỉ muốn mã trả về giá trị null

Bất kỳ ý tưởng ?

Trân trọng

Hỏi ngày 22 tháng 8 năm 2016 lúc 12:29Aug 22, 2016 at 12:29

Hướng dẫn spring mongodb enum mapping - bản đồ mùa xuân mongodb enum

2

Bạn có thể thêm một trình chuyển đổi tùy chỉnh triển khai

public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
1 Có bạn triển khai logic chuyển đổi của riêng bạn từ chuỗi sang enum của bạn.

một cái gì đó như thế này

public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}

Để ý !!! Bộ chuyển đổi này sẽ cố gắng chuyển đổi từng chuỗi trong Mongo thành Enum của bạn, do đó có thể dẫn đến các chuyển đổi không mong muốn, vì vậy hãy đảm bảo bạn chỉ làm điều này khi cần. Bạn có thể thêm

public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
2 nếu bạn muốn chuyển đổi này khi đọc từ Mongo. This converter will try to convert each string in mongo to your enum, thus may result in unwanted conversions, so make sure you do this only when needed. you can add
public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
2 if you want this convert only when reading from mongo.

Đã trả lời ngày 24 tháng 7 năm 2017 lúc 17:06Jul 24, 2017 at 17:06

YoniyoniYoni

3452 Huy hiệu bạc18 Huy hiệu đồng2 silver badges18 bronze badges

Okay, Done!

Download code ví dụ trên tại đây.

Code ví dụ Hibernate @Enumerated, lưu dữ liệu dạng Enum.

(Xem thêm: Hướng dẫn tự học Hibernate)

  • Khi thực hiện insert dữ liệu, khai báo kiểu dữ liệu, thay vì dùng kiểu String, ta dùng kiểu Enum như thế khi code sẽ đảm bảo được giữ liệu chỉ nhận các giá trị nhất định.
  • Các công nghệ sử dụng:
  • Maven
  • JDK 1.8

Eclipse

CREATE SCHEMA `hibernate-demo-1` ;

CREATE TABLE `hibernate-demo-1`.`employee` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `position` VARCHAR(45) NULL,
  PRIMARY KEY (`id`));

MySQL

Tạo database MySQL

Hướng dẫn spring mongodb enum mapping - bản đồ mùa xuân mongodb enum

Đối tượng employee có column position (vai trò) . Bây giờ mình chỉ muốn position nhận các giá trị cố định

public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
3 thì trong code mình sẽ tạo Enum với các thể hiện trên và dùng nó là type cho field position


  4.0.0
  stackjava.com
  HibernateEnumDemo
  0.0.1-SNAPSHOT

  
    1.8
    1.8
    5.3.6.Final
  

  
    
      org.hibernate
      hibernate-core
      ${hibernate.version}
    
    
      org.hibernate
      hibernate-entitymanager
      ${hibernate.version}
    
    
      mysql
      mysql-connector-java
      5.1.46
    
  


Cấu trúc Project


  
    Demo Hibernate Enumerated
    org.hibernate.jpa.HibernatePersistenceProvider
    
      
      
      
      
      
    
  

Các thư viện sử dụng

File cấu hình hibernate, kết nối tới MySQL

Trong ví dụ này mình sử dụng

public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
4 nên sẽ khai báo file
public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
5 nếu các bạn sử dụng
public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
6 thì có thể khai báo file
public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
7

package stackjava.com.hibernatedemo.entities;

public enum PositionEnum {
  DEVELOPER, TESTER, MANAGER, QA, BA;
}

File entity

package stackjava.com.hibernatedemo.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "employee")
public class Employee {

  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;
  
  @Column(name = "name")
  private String name;
  
  @Column(name = "position")
  @Enumerated(EnumType.STRING)
  private PositionEnum position;

  // getter - setter

  @Override
  public String toString() {
    return "Employee [id=" + id + ", name=" + name + ", position=" + position + "]";
  }
  
  
}

Annotation

public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
9 sẽ đánh dấu field được lưu dạng enum, khi lưu vào database và đọc từ database ra, nó sẽ tự động lấy name của Enum đó.

Demo 1:

Insert đối tượng employee với field postion là 1 enum

package stackjava.com.hibernatedemo.dao;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import stackjava.com.hibernatedemo.entities.Employee;
import stackjava.com.hibernatedemo.entities.PositionEnum;

public class DemoSave {

  public static void main(String[] args) {
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    
    Employee emp = new Employee();
    emp.setName("kai");
    emp.setPosition(PositionEnum.DEVELOPER);
    entityManager.persist(emp);
    
    entityManager.getTransaction().commit();
    System.out.println("---------- after save ---------------");
    System.out.println(emp);
    entityManager.close();
    entityManagerFactory.close();
  }

}

Kết quả:

Hibernate: insert into employee (name, position) values (?, ?)
---------- after save ---------------
Employee [id=1, name=kai, position=DEVELOPER]

Hướng dẫn spring mongodb enum mapping - bản đồ mùa xuân mongodb enum

Demo 2:

Đọc dữ liệu từ database và gán vào field Enum.

package stackjava.com.hibernatedemo.dao;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import stackjava.com.hibernatedemo.entities.Employee;

public class DemoSelect {

  public static void main(String[] args) {
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();
    
    Employee emp = entityManager.find(Employee.class, 1);
    System.out.println(emp);
    
    entityManager.getTransaction().commit();
    entityManager.close();
    entityManagerFactory.close();
  }

}

Kết quả:

public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
0

Demo 2:

Đọc dữ liệu từ database và gán vào field Enum.

Nếu bạn vào database và sửa giá trị column position thành 1 giá trị khác không nằm trong các giá trị 

public class OrderOptionEnumMongoConverter implements Converter {

    @Override
    public OrderOptionEnum convert(String source) {

        for (OrderOptionEnum OrderOptionEnum : OrderOptionEnum.values()) {
            if (OrderOptionEnum.name().equals(source))
                return OrderOptionEnum;
        }

        return null;
    }
}
3 nó sẽ báo lỗi vì không thể convert từ giá trị đó sang
CREATE SCHEMA `hibernate-demo-1` ;

CREATE TABLE `hibernate-demo-1`.`employee` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `position` VARCHAR(45) NULL,
  PRIMARY KEY (`id`));
1

References:

https://docs.jboss.org/…/html_single/#basic-enums