| 知乎专栏 |
@ElementCollection 很像 @OneToMany,甚至有些场景可以相互替代,@ElementCollection 更适合 List/Set/Map/Array 等数据类型,而 @OneToMany 是对应一个实体。
ElementCollection 缺点是,不能对集合表进行 CURD操作
import javax.persistence.*;
import java.util.*;
import javax.persistence.*;
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@ElementCollection
private Set<Address> address = new HashSet<Address>();
}
import javax.persistence.*;
@Embeddable
public class Address {
private String province;
private String city;
private String state;
}
List 集合
@ElementCollection(targetClass = String.class) //指定集合中元素的类型 @CollectionTable(name = "school_inf", joinColumns = @JoinColumn(name="pid",nullable = false)) //表示外键不能为空 @Column(name = "school_name") //指定表中保存集合元素的列名 @OrderColumn(name = "list_order") //索引列 private List<String> schools = new ArrayList<String>();
数组集合
@Entity
@Table
public class Student {
@Id @Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer sid;
private String name;
private Integer age;
@ElementCollection(targetClass=String.class) //集合中元素的类型
@CollectionTable(name = "school", joinColumns = @JoinColumn(name="sid",nullable = false))//指定外键的名称为sid,并且不能为空
@Column(name = "school_name") //指定schools属性,在表中的列名
@OrderColumn(name = "array_order")
private String[] schools = new String[3];
}
Map 集合
@Entity
@Table(name = "student")
public class Student {
@Id @Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer sid;
private String name;
private Integer age;
@ElementCollection(targetClass = Float.class) //对于Map类型的属性:指定的是Value的类型
@CollectionTable(name = "score_info", joinColumns = @JoinColumn(name="sid", nullable = false))
@MapKeyClass(String.class) // 指定Map中key的类型
@MapKeyColumn(name="suject") //指定索引列,也就是key的列名
@Column(name = "score") //映射保存Map, Value的列名
private Map<String, Float> scores = new HashMap<String, Float>(); //科目和成绩
}
Set 集合
@ElementCollection
private final Set<String> address = new HashSet<String>();
@ElementCollection
@CollectionTable(joinColumns = @JoinColumn(name = "pid", nullable = false))
private Set<Status> address = new HashSet<Status>();
package cn.netkiller.domain;
import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table
@DynamicUpdate
@DynamicInsert
@Data
@Comment("Stable Diffusion Lora 表")
public class Lora implements Serializable {
@Serial
public static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false, insertable = false, updatable = false, columnDefinition = "int unsigned")
@Comment("主键")
private Long id;
@Column(unique = true, nullable = false, insertable = true, updatable = true)
@Comment("模型名称")
private String name;
@Comment("模型描述")
private String description;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> keyword = new HashSet<String>();
@Comment("状态")
private boolean status;
@Column(insertable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
@Comment("创建时间")
private Date ctime;
@Column(nullable = true, insertable = false, updatable = false, columnDefinition = "TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP")
@Comment("修改时间")
private Date mtime;
}
package cn.netkiller.repository;
import cn.netkiller.domain.Lora;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import java.util.Set;
@Repository
public interface LoraRepository extends CrudRepository<Lora, Integer> {
}
package cn.netkiller.controller;
import cn.netkiller.domain.Lora;
import cn.netkiller.repository.LoraRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
import java.util.Set;
@RestController
@Slf4j
@RequestMapping("/lora")
public class LoraController {
@Autowired
private LoraRepository loraRepository;
@GetMapping("test")
public Lora test() {
Lora lora = new Lora();
lora.setName("中国风");
lora.setDescription("中国风格图片");
lora.setKeyword(Set.of("茶", "武术", "剪纸"));
loraRepository.save(lora);
lora = new Lora();
lora.setName("二次元");
lora.setDescription("二次元风格图片");
lora.setKeyword(Set.of("日本", "机甲", "手办"));
loraRepository.save(lora);
return lora;
}
@GetMapping("query")
public Iterable<Lora> query() {
Iterable<Lora> lora = loraRepository.findAll();
return lora;
}
}
@ElementCollection
@CollectionTable(joinColumns = @JoinColumn(name = "pid", nullable = false))
private Set<Status> address = new HashSet<Status>();
集合表子查询,以Set为例
package cn.netkiller.repository;
import cn.netkiller.domain.Lora;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import java.util.Set;
@Repository
public interface LoraRepository extends CrudRepository<Lora, Integer> {
Optional<Lora> findByKeywordIn(Set keyword);
}
查询接口
@GetMapping("keyword")
public Optional<Lora> keywordTest(@RequestParam("key") Set<String> keyword) {
Optional<Lora> lora = loraRepository.findByKeywordIn(keyword);
return lora;
}
GET 传递 Set 参数的方法如下
curl -X 'GET' \ 'http://localhost:8080/lora/keyword?key=%E8%8C%B6&key=%E6%AD%A6%E6%9C%AF&key=%E9%80%A0%E7%BA%B8' \ -H 'accept: */*'