赞
踩
参考文章:
JPA概念解析:CascadeType(各种级联操作)详解
@Data
在JPA中要慎用,因为重写的toString、equals、hashCode都会将关联的实体类对象包含进去,导致执行查询时循环调用到栈溢出
建议:
@Data
、@EqualsAndHashCode
、@ToString
,重写toString、equals和hashCode@EqualsAndHashCode
,但要通过属性exclude去掉集合类型的属性,例如:@EqualsAndHashCode(exclude = {"blogs","roles"})
。/** * @Description 用户表 * @author Evad.Wu * @date 2022-06-16 */ @Setter @Getter @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(exclude = {"blogs","roles"}) @Accessors(chain = true) @Entity @Table(name = "user") public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @GenericGenerator(name = "idGenerator", strategy = "uuid") @GeneratedValue(generator = "idGenerator") @Column(name = "id") private Long id; @Column(name = "username") private String username; @Column(name = "avatar") private String avatar; @Column(name = "email") private String email; @Column(name = "password") private String password; @Column(name = "status") private Integer status; @Column(name = "created") private Date created; @Column(name = "last_login") private Date lastLogin; @Column(name = "admin") private boolean admin; @Column(name = "telephone") private String telephone; @Column(name = "identification") private String identification; @Column(name = "introduction") private String introduction; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL,fetch = FetchType.LAZY) private Set<Blog> blogs; @ManyToMany(targetEntity = Role.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY) @JoinTable(name = "tb_user_role", joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}) private Set<Role> roles; @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", avatar='" + avatar + '\'' + ", email='" + email + '\'' + ", password='" + password + '\'' + ", status=" + status + ", created=" + created + ", lastLogin=" + lastLogin + ", admin=" + admin + ", telephone='" + telephone + '\'' + ", identification='" + identification + '\'' + ", introduction='" + introduction + '\'' + '}'; } }
/** * @Description 博客表 * @author Evad.Wu * @date 2022-06-17 */ @Setter @Getter @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(exclude = {"reviewSet","user"}) @Accessors(chain = true) @Entity @Table(name = "blog") public class Blog implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "user_id") private Long userId; @Column(name = "examine_id") private String examineId; @Column(name = "title") private String title; @Column(name = "description") private String description; @Column(name = "content") private String content; @Column(name = "created") private Date created; @Column(name = "status") private Integer status; @Column(name = "index_img") private String indexImg; @Column(name = "reading") private Long reading; @ManyToOne(targetEntity = User.class,cascade = CascadeType.ALL,fetch = FetchType.LAZY) @JoinColumn(name = "user_id",insertable = false,updatable = false) private User user; @Override public String toString() { return "Blog{" + "id=" + id + ", userId=" + userId + ", examineId='" + examineId + '\'' + ", title='" + title + '\'' + ", description='" + description + '\'' + ", content='" + content + '\'' + ", created=" + created + ", status=" + status + ", indexImg='" + indexImg + '\'' + ", reading=" + reading + '}'; } }
@Setter @Getter @NoArgsConstructor @AllArgsConstructor @ToString @EqualsAndHashCode(callSuper = false) @Builder @Entity @Table(name = "tb_role") public class Role extends BaseModel implements Serializable { private static final long serialVersionUID = 2480455193854374245L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(name = "role_code") private String roleCode; @Column(name = "role_name") private String roleName; }
@Data @MappedSuperclass @DynamicInsert @EntityListeners(AuditingEntityListener.class) public class BaseModel implements Serializable { private static final long serialVersionUID = -1152053885220920998L; /** * 创建人 */ @CreatedBy @Column(name = "creator", updatable = false, length = 64) private String creator; /** * 创建时间 */ @CreatedDate @Column(name = "create_time", updatable = false) private Date createTime; /** * 修改人 */ @LastModifiedBy @Column(name = "modifier", length = 64) private String modifier; /** * 修改时间 */ @LastModifiedDate @Column(name = "modify_time") private Date modifyTime; /** * 数据可见 */ @Column(name = "visible",columnDefinition = "TINYINT DEFAULT 1") @ColumnDefault("1") private Boolean visible; /** * 版本 */ @Version @Column(name = "rec_ver") private Long recVer; }
区别只是类型是单个对象还是集合对象
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL,fetch = FetchType.LAZY)
private Set<Blog> blogs;
@ManyToOne(targetEntity = User.class,cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name = "user_id",insertable = false,updatable = false)
private User user;
一对多要相互依赖,首先有多对一,这里Blog类中需要定义一个User,并添加注解@JoinColumn
,指定name关联的字段。
然后User类中需要定义Blog集合,接收多个Blog对象
注意:insertable和updatable都置为false,因为Blog类中的userId和User类中的id都指向同一个数据库字段,这样就会导致级联更新时重复修改而报错。
/** * 一对多 1: User N: Blog */ @Test public void oneMore() { List<Long> userIds = new ArrayList<>(); userIds.add(2L); userIds.add(4L); List<User> userList = userRepository.findAllById(userIds); for (User user : userList) { System.out.println("user: " + user); Set<Blog> blogs = user.getBlogs(); for (Blog blog : blogs) { System.out.println("blog: " + blog); } } }
/**
* 多对一 N: Blog 1: User
*/
@Test
public void moreOne() {
List<Long> blogIds = new ArrayList<>();
blogIds.add(9L);
blogIds.add(10L);
List<Blog> blogList = blogRepository.findAllById(blogIds);
for (Blog blog : blogList) {
System.out.println("blogId: " + blog.getId());
System.out.println("user: " + blog.getUser());
}
}
/** * @Description 角色 * @author Evad.Wu * @date 2022-06-21 */ @Setter @Getter @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(exclude = {"reviewSet","user"}) @Entity @Table(name = "tb_role") public class Role { @Id @GenericGenerator(name = "idGenerator", strategy = "uuid") @GeneratedValue(generator = "idGenerator") private String id; @Column(name = "user_id") private Long userId; @Column(name = "role_name") private String roleName; @Override public String toString() { return "Role{" + "id='" + id + '\'' + ", userId=" + userId + ", roleName='" + roleName + '\'' + '}'; } }
@ManyToMany(targetEntity = Role.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@JoinTable(name = "tb_user_role",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
private Set<Role> roles;
@JoinColumn
的name属性对应中间表中两端的连接字段,referencedColumnName则是每张表中用于连接的字段/**
* 多对多:N: User N: Role / N: Role N: User
*/
@Test
public void userRoleM2M() {
Optional<User> userOptional = userRepository.findById(51L);
User user = userOptional.get();
System.out.println("userId: " + user.getId());
Set<Role> roles = user.getRoles();
for (Role role : roles) {
System.out.println("role: " + role);
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。