用一个简单的TaskResult Entity来作为例子。
这个Entity有四个attributes:
- 主键Id
- 所属的Task
- 可能的结果的名称,称之为key
- 最终结果是某key的可能性probability
最开始的时候,我们希望key是一个短整型,所以我们用short来表示它,整个对象代码如下:
package cn.com.spinq.quantumCloudComputingService.task.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Data
@Table(name = "task_result")
public class TaskResult {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "tr_id", nullable = false)
private long trid;
@ManyToOne
@JoinColumn(name = "task_id", referencedColumnName = "t_id", nullable = false)
private Task task;
@Column(name = "key", nullable = false)
private short key;
@Column(name = "probability", nullable = false)
private double probability;
public TaskResult() {
}
public TaskResult(Task t, short s, double p) {
task = t;
key = s;
probability = p;
}
}
我们用一个JUnit Test Case测试这个类。
package cn.com.spinq.quantumCloudComputingService.task;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import cn.com.spinq.quantumCloudComputingService.task.entity.Task;
import cn.com.spinq.quantumCloudComputingService.task.entity.TaskResult;
import cn.com.spinq.quantumCloudComputingService.task.repository.TaskRepository;
import cn.com.spinq.quantumCloudComputingService.task.repository.TaskResultRepository;
@SpringBootTest
class AutoUpdateTest {
@Autowired
private TaskRepository taskRepository;
@Autowired
private TaskResultRepository taskResultRepository;
@Test
void test() {
Task t = taskRepository.findByTid(9);
TaskResult tr1 = new TaskResult(t, (short) 0, 25.56);
TaskResult tr2 = new TaskResult(t, (short) 1, 35.4);
taskResultRepository.save(tr1);
taskResultRepository.save(tr2);
}
}
SpringBoot会在第一次载入类的时候帮我们自动生成对应的表,用show create table <tablename>
查看表格结构,对应如下。
CREATE TABLE `task_result` (
`tr_id` bigint NOT NULL AUTO_INCREMENT,
`probability` double NOT NULL,
`key` smallint NOT NULL,
`task_id` bigint NOT NULL,
PRIMARY KEY (`tr_id`),
KEY `FKq69p1l61s4ytx1ob6e3jmual8` (`task_id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
现在,我们希望将key的类型从short变为12位长的二进制字节码,同时我们还希望添加一个Unique Union Key,于是我们改变TaskResult Class的代码。
package cn.com.spinq.quantumCloudComputingService.task.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import lombok.Data;
@Entity
@Data
@Table(name = "task_result", uniqueConstraints = {@UniqueConstraint(columnNames = {"task_id","key"})})
public class TaskResult {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "tr_id", nullable = false)
private long trid;
@ManyToOne
@JoinColumn(name = "task_id", referencedColumnName = "t_id", nullable = false)
private Task task;
@Column(name = "key", nullable = false, length=12)
private String key;
@Column(name = "probability", nullable = false)
private double probability;
public TaskResult() {
}
public TaskResult(Task t, String s, double p) {
task = t;
key = s;
probability = p;
}
}
更新我们对应的JUnit Test Case,再跑一次。
@SpringBootTest
class AutoUpdateTest {
@Autowired
private TaskRepository taskRepository;
@Autowired
private TaskResultRepository taskResultRepository;
@Test
void test() {
Task t = taskRepository.findByTid(9);
TaskResult tr1 = new TaskResult(t, "10", 22.3);
TaskResult tr2 = new TaskResult(t, "11", 55.0);
taskResultRepository.save(tr1);
taskResultRepository.save(tr2);
}
}
刷新数据库,再次查看表格结构,会发现Unique Key已经加进去了,然而key的数据类型并没有改变。如果key一直都只输入二进制字符串,则数据类型一直不会改变。
CREATE TABLE `task_result` (
`tr_id` bigint NOT NULL AUTO_INCREMENT,
`probability` double NOT NULL,
`key` smallint NOT NULL,
`task_id` bigint NOT NULL,
PRIMARY KEY (`tr_id`),
UNIQUE KEY `UK4k3caerdax5wteynoum8ipqwb` (`task_id`,`key`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
如果这时用Test插入key为String的对象,数据库会报错。
@Test
void test() {
Task t = taskRepository.findByTid(9);
TaskResult tr1 = new TaskResult(t, "abcd", 22.3);
taskResultRepository.save(tr1);
}
2020-07-16 15:38:59.861 WARN 7408 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1366, SQLState: HY000
2020-07-16 15:38:59.861 ERROR 7408 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : Incorrect integer value: 'abcd' for column 'key' at row 1
2020-07-16 15:38:59.882 INFO 7408 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-07-16 15:38:59.883 INFO 7408 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
只有把表删了重新生成一遍才能得到正确的结构。
CREATE TABLE `task_result` (
`tr_id` bigint NOT NULL AUTO_INCREMENT,
`probability` double NOT NULL,
`key` varchar(12) NOT NULL,
`task_id` bigint NOT NULL,
PRIMARY KEY (`tr_id`),
UNIQUE KEY `UK4k3caerdax5wteynoum8ipqwb` (`task_id`,`key`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
由此可见,spring.jpa.hibernate.ddl-auto=update可以为已存在的表添加以前没有的属性,但无法替换已经存在的表的数据类型和值。
网友评论