如何在 Hibernate 中将 @ElementCollection List<String> 转换为 @ElementCollection List<CustomObject> 而不丢失数据?

问题描述 投票:0回答:1

我有一个 Hibernate

Employee
实体,其中有一个名为
List<String>
addresses
字段,使用
@ElementCollection
@CollectionTable
进行映射。当前的设置如下所示:

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ElementCollection
    @CollectionTable(name = "employee_addresses", joinColumns = @JoinColumn(name = "employee_id"))
    @Column(name = "address")
    private List<String> addresses;

    // other fields, getters, and setters
}

我想将

addresses
字段重构为
List<Address>
,其中
Address
是一个
@Embeddable
类。这是新的 Address 类:

@Embeddable
public class Address {
    private String address;
    private AddressTypeEnum addressType;

    // other fields, getters, setters, constructors
}

更新后的

Employee
实体:

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ElementCollection
    @CollectionTable(name = "employee_addresses", joinColumns = @JoinColumn(name = "employee_id"))
    private List<Address> addresses;

    // other fields, getters, and setters
}

将现有数据从

List<String>
迁移到
List<Address>
同时保留
employee_addresses
表中的数据的最佳方法是什么?我需要确保地址列中的数据正确传输到Address类的地址字段中。

任何指导或建议将不胜感激。谢谢!

java hibernate jpa orm jpa-2.0
1个回答
0
投票

您可以编写迁移脚本来更新employee_addresses表并修改列类型(如果需要)。例如,您可能需要在employee_addresses 表中为address_type 引入一个新列(假设AddressTypeEnum 是Address 对象的一部分)。

添加address_type列(如果它是您要存储在employee_addresses表中的新列)。

ALTER TABLE employee_addresses ADD COLUMN address_type VARCHAR(255);

填充新列(如果 AddressTypeEnum 是迁移的一部分)。为简单起见,您可以将 address_type 默认为某个值。

UPDATE employee_addresses SET address_type = 'DEFAULT'; -- Set a default value (adjust according to your logic)

如果不再需要,也可以删除旧色谱柱

ALTER TABLE employee_addresses DROP COLUMN address;

用 Java 填充列表

数据库模式准备就绪后,您需要编写 Java 代码来加载现有数据并将 String 值转换为 Address 对象。

如果您使用的是 Spring Boot 应用程序,您可以创建一个将在启动时运行的一次性迁移方法。该方法可以获取所有员工记录,迁移地址,并保存更新的实体。

@Service
public class EmployeeMigrationService {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private AddressRepository addressRepository; // Optional, if you need to save Address separately

    @Transactional
    public void migrateEmployeeAddresses() {
        List<Employee> employees = employeeRepository.findAll();
        for (Employee employee : employees) {
            List<String> oldAddresses = employee.getOldAddresses(); // Assuming you have a getter for the old addresses
            if (oldAddresses != null && !oldAddresses.isEmpty()) {
                List<Address> newAddresses = oldAddresses.stream()
                        .map(addressStr -> new Address(addressStr, AddressTypeEnum.DEFAULT)) // Adjust AddressTypeEnum mapping as needed
                        .collect(Collectors.toList());
                employee.setAddresses(newAddresses);
                employeeRepository.save(employee);
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.