SpringBoot + JPA @ManyToMany的操作要點(diǎn)說(shuō)明
SpringBoot + JPA @ManyToMany 要點(diǎn)
這里主要時(shí)記錄下此種方法的注意事項(xiàng)。
環(huán)境 :mysql 引擎為innoDB ,否則沒(méi)有事務(wù)的說(shuō)法的。
#不加這句則默認(rèn)為myisam引擎 spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
對(duì)應(yīng)的Entity的建立
此處注意不可使用lombok @Data 注解。使用@Setter 、@Getter注解。主要原因時(shí)要自己覆寫(xiě)hash() equals(),toString() 方法。這樣添加和刪除的時(shí)候不會(huì)出現(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的測(cè)試
注意@transaction的注解一定要加上。并且@Rollback(value = false) 也加上。springboot-test 默認(rèn)在內(nèi)存中save,不提交,所有以通過(guò)了但是數(shù)據(jù)庫(kù)中無(wú)內(nèi)容,官方說(shuō)為了不影響上下文環(huán)境。
/** * 添加角色 */ @Test public void addRole(){ Role role = new Role(); role.setName("系統(tǒng)管理員"); roleRepository.save(role); } /** * 添加用戶(hù) */ @Test public void addUser() { User user = new User(); user.setUsername("test1"); userRepostitory.save(user); } /** * * 通過(guò)關(guān)系維護(hù)方添加角色和用戶(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); } /** * * 刪除對(duì)應(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)的主要問(wèn)題在 toString()方法。此方法只能包含基本的元素,不要包含相應(yīng)的@ManyToMany 的對(duì)象。兩個(gè)類(lèi)都是。這樣才會(huì)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); } /** * 添加用戶(hù) */ @Test public void addUser() { User user = new User(); user.setUsername("test1"); userRepostitory.save(user); } /** * * 通過(guò)關(guān)系維護(hù)方添加角色和用戶(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); } /** * * 刪除對(duì)應(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); } /** * * 刪除用戶(hù)不能聯(lián)動(dòng)刪除關(guān)系, * 這個(gè)時(shí)不能執(zhí)行的,只能在數(shù)據(jù)維護(hù)端來(lái)進(jìn)行刪除后,在進(jìn)行相應(yīng)的用戶(hù)刪除。 * */ @Test public void removeUser(){ Role role = roleRepository.getOne(2); User user = userRepostitory.findByUsername("test1"); role.removeUser(user); userRepostitory.delete(user); }
JPA中ManyToMany關(guān)系問(wèn)題
配置JPA的時(shí)候多對(duì)多關(guān)系,報(bào)以下錯(cuò)誤:
org.hibernate.AnnotationException: Illegal use of mappedBy on both sides of the relationship: com.csair.gme.core.domain.ComponentType.componentPropertys
解決辦法
不能兩邊都用mappedBy,只能用一邊,而且用mappedBy的那一邊是從表,另外一邊就是主表。mappedBy=‘主表里的變量名'
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
jdk7 中HashMap的知識(shí)點(diǎn)總結(jié)
HashMap的原理是老生常談了,不作仔細(xì)解說(shuō)。一句話(huà)概括為HashMap是一個(gè)散列表,它存儲(chǔ)的內(nèi)容是鍵值對(duì)(key-value)映射。這篇文章主要總結(jié)了關(guān)于jdk7 中HashMap的知識(shí)點(diǎn),需要的朋友可以參考借鑒,一起來(lái)看看吧。2017-01-01SpringBoot自定義全局異常處理器的問(wèn)題總結(jié)
Springboot框架提供兩個(gè)注解幫助我們十分方便實(shí)現(xiàn)全局異常處理器以及自定義異常,處理器會(huì)優(yōu)先處理更具體的異常類(lèi)型,如果沒(méi)有找到匹配的處理器,那么它會(huì)尋找處理更一般異常類(lèi)型的處理器,本文介紹SpringBoot自定義全局異常處理器的問(wèn)題,一起看看吧2024-01-01JAVA后端學(xué)習(xí)精華之網(wǎng)絡(luò)通信項(xiàng)目進(jìn)階
不同項(xiàng)目之間的通信方式分為,http、socket、webservice;其中socket通信的效率最高,youtube就采用的是原始的socket通信,他們信奉的原則是簡(jiǎn)單有效2021-09-09java設(shè)計(jì)模式責(zé)任鏈模式原理案例詳解
一個(gè)事件需要經(jīng)過(guò)多個(gè)對(duì)象處理是一個(gè)挺常見(jiàn)的場(chǎng)景,譬如采購(gòu)審批流程,請(qǐng)假流程,軟件開(kāi)發(fā)中的異常處理流程,web請(qǐng)求處理流程等各種各樣的流程,可以考慮使用責(zé)任鏈模式來(lái)實(shí)現(xiàn)2021-09-09SpringBoot使用WebSocket的方法實(shí)例詳解
WebSocket 是 HTML5 開(kāi)始提供的一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議。這篇文章主要介紹了SpringBoot使用WebSocket,需要的朋友可以參考下2019-06-06Spring?Cloud?Sleuth?和?Zipkin?進(jìn)行分布式跟蹤使用小結(jié)
分布式跟蹤是一種機(jī)制,我們可以使用它跟蹤整個(gè)分布式系統(tǒng)中的特定請(qǐng)求,分布式跟蹤允許您跟蹤分布式系統(tǒng)中的請(qǐng)求,本文給大家介紹Spring?Cloud?Sleuth?和?Zipkin?進(jìn)行分布式跟蹤使用小結(jié),感興趣的朋友一起看看吧2022-03-03java arrayList遍歷的四種方法及Java中ArrayList類(lèi)的用法
arraylist是動(dòng)態(tài)數(shù)組,它具有三個(gè)好處分別是:動(dòng)態(tài)的增加和減少元素 、實(shí)現(xiàn)了ICollection和IList接口、靈活的設(shè)置數(shù)組的大小,本文給大家介紹java arraylist遍歷及Java arraylist 用法,感興趣的朋友一起學(xué)習(xí)吧2015-11-11使用String類(lèi)型小數(shù)值轉(zhuǎn)換為L(zhǎng)ong類(lèi)型
這篇文章主要介紹了使用String類(lèi)型小數(shù)值轉(zhuǎn)換為L(zhǎng)ong類(lèi)型操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09