SpringBoot + JPA @ManyToMany的操作要點說明
SpringBoot + JPA @ManyToMany 要點
這里主要時記錄下此種方法的注意事項。
環(huán)境 :mysql 引擎為innoDB ,否則沒有事務(wù)的說法的。
#不加這句則默認(rèn)為myisam引擎 spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
對應(yīng)的Entity的建立
此處注意不可使用lombok @Data 注解。使用@Setter 、@Getter注解。主要原因時要自己覆寫hash() equals(),toString() 方法。這樣添加和刪除的時候不會出現(xiàn)異常。否則出現(xiàn)循環(huán)的引用,不能刪除或stackOver;
User
@Setter @Getter @Entity public class User { @Id @GenericGenerator(name="jpauuid",strategy = "org.hibernate.id.UUIDGenerator") @GeneratedValue(generator = "jpauuid") @Column(length = 32,nullable = false) private String id; @Column(length = 30) private String username; @ManyToMany(cascade = CascadeType.REFRESH,mappedBy = "users") private Set<Role> roles; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return id.equals(user.id) && username.equals(user.username) && roles.equals(user.roles); } @Override public int hashCode() { return Objects.hash(id, username, roles); } @Override public String toString() { return "User{" + "id='" + id + '\'' + ", username='" + username + '\'' + ", roles=" + roles + '}'; } }
Role
@Setter @Getter @Entity public class Role { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; @Column(length = 30) private String name; @ManyToMany(cascade = CascadeType.REFRESH) @JoinTable(name = "user_role",joinColumns = @JoinColumn(name = "role_id"),inverseJoinColumns = @JoinColumn(name="user_id")) private Set<User> users; public void addUser(User user){ this.users.add(user); } public void removeUser(User user){ this.users.remove(user); } }
Junit的測試
注意@transaction的注解一定要加上。并且@Rollback(value = false) 也加上。springboot-test 默認(rèn)在內(nèi)存中save,不提交,所有以通過了但是數(shù)據(jù)庫中無內(nèi)容,官方說為了不影響上下文環(huán)境。
/** * 添加角色 */ @Test public void addRole(){ Role role = new Role(); role.setName("系統(tǒng)管理員"); roleRepository.save(role); } /** * 添加用戶 */ @Test public void addUser() { User user = new User(); user.setUsername("test1"); userRepostitory.save(user); } /** * * 通過關(guān)系維護(hù)方添加角色和用戶的關(guān)系 */ @Test @Transactional @Rollback(value = false) public void addUserRole(){ User user = userRepostitory.findByUsername("test1"); Role role = roleRepository.getOne(1); role.addUser(user); roleRepository.saveAndFlush(role); } /** * * 刪除對應(yīng)的關(guān)聯(lián)數(shù)據(jù) */ @Test @Transactional public void removeRoleUser(){ User user = userRepostitory.findByUsername("test1"); Role role = roleRepository.getOne(1); role.removeUser(user); roleRepository.saveAndFlush(role); }
不能刪除和添加成功,出現(xiàn)循環(huán)的主要問題在 toString()方法。此方法只能包含基本的元素,不要包含相應(yīng)的@ManyToMany 的對象。兩個類都是。這樣才會ok.
@RunWith(SpringRunner.class) @SpringBootTest public class DemoBeetlApplicationTests { @Autowired private UserRepostitory userRepostitory; @Autowired private RoleRepository roleRepository; @Autowired private UserGroupRepository userGroupRepository; @Autowired private PriviledgeRepository priviledgeRepository; @Autowired private MenuRepository menuRepository; @Autowired private FileRepository fileRepository; @Autowired private ElementRepository elementRepository; @Autowired private OperationRepository operationRepository; @Test public void contextLoads() { System.out.println("helle junit"); } /** * 添加角色 */ @Test public void addRole(){ Role role = new Role(); role.setName("系統(tǒng)管理員"); roleRepository.save(role); } /** * 添加用戶 */ @Test public void addUser() { User user = new User(); user.setUsername("test1"); userRepostitory.save(user); } /** * * 通過關(guān)系維護(hù)方添加角色和用戶的關(guān)系 * * */ @Test @Transactional @Rollback(value = false) public void addRoleUser(){ User user = userRepostitory.findByUsername("test1"); Role role = roleRepository.getOne(2); role.addUser(user); roleRepository.saveAndFlush(role); } /** * * 刪除對應(yīng)的關(guān)聯(lián)數(shù)據(jù) */ @Test @Transactional @Rollback(value = false) public void removeRoleUser(){ Role role = roleRepository.getOne(2); User user = userRepostitory.findByUsername("test1"); role.removeUser(user); roleRepository.saveAndFlush(role); } /** * * 刪除單一的角色是可以刪除相應(yīng)的關(guān)系 */ @Test public void removeRole(){ Role role = roleRepository.getOne(2); roleRepository.delete(role); } /** * * 刪除用戶不能聯(lián)動刪除關(guān)系, * 這個時不能執(zhí)行的,只能在數(shù)據(jù)維護(hù)端來進(jìn)行刪除后,在進(jìn)行相應(yīng)的用戶刪除。 * */ @Test public void removeUser(){ Role role = roleRepository.getOne(2); User user = userRepostitory.findByUsername("test1"); role.removeUser(user); userRepostitory.delete(user); }
JPA中ManyToMany關(guān)系問題
配置JPA的時候多對多關(guān)系,報以下錯誤:
org.hibernate.AnnotationException: Illegal use of mappedBy on both sides of the relationship: com.csair.gme.core.domain.ComponentType.componentPropertys
解決辦法
不能兩邊都用mappedBy,只能用一邊,而且用mappedBy的那一邊是從表,另外一邊就是主表。mappedBy=‘主表里的變量名'
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot自定義全局異常處理器的問題總結(jié)
Springboot框架提供兩個注解幫助我們十分方便實現(xiàn)全局異常處理器以及自定義異常,處理器會優(yōu)先處理更具體的異常類型,如果沒有找到匹配的處理器,那么它會尋找處理更一般異常類型的處理器,本文介紹SpringBoot自定義全局異常處理器的問題,一起看看吧2024-01-01JAVA后端學(xué)習(xí)精華之網(wǎng)絡(luò)通信項目進(jìn)階
不同項目之間的通信方式分為,http、socket、webservice;其中socket通信的效率最高,youtube就采用的是原始的socket通信,他們信奉的原則是簡單有效2021-09-09Spring?Cloud?Sleuth?和?Zipkin?進(jìn)行分布式跟蹤使用小結(jié)
分布式跟蹤是一種機(jī)制,我們可以使用它跟蹤整個分布式系統(tǒng)中的特定請求,分布式跟蹤允許您跟蹤分布式系統(tǒng)中的請求,本文給大家介紹Spring?Cloud?Sleuth?和?Zipkin?進(jìn)行分布式跟蹤使用小結(jié),感興趣的朋友一起看看吧2022-03-03java arrayList遍歷的四種方法及Java中ArrayList類的用法
arraylist是動態(tài)數(shù)組,它具有三個好處分別是:動態(tài)的增加和減少元素 、實現(xiàn)了ICollection和IList接口、靈活的設(shè)置數(shù)組的大小,本文給大家介紹java arraylist遍歷及Java arraylist 用法,感興趣的朋友一起學(xué)習(xí)吧2015-11-11使用String類型小數(shù)值轉(zhuǎn)換為Long類型
這篇文章主要介紹了使用String類型小數(shù)值轉(zhuǎn)換為Long類型操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09