SpringBootjpa注解@ElementCollection实现⼀对多关联环境:
jdk: openjdk11
springboot: 2.2
操作系统: win10教育版 1903
1. l (jpa依赖主要在 jpa-redis注释下的两个)
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"
3        xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
4<modelVersion>4.0.0</modelVersion>
5<parent>
6<groupId>org.springframework.boot</groupId>
7<artifactId>spring-boot-starter-parent</artifactId>
8<version>2.2.4.RELEASE</version>
9<relativePath/><!-- lookup parent from repository -->
10</parent>
11<groupId>com.rurjs</groupId>
12<artifactId>starter</artifactId>
13<version>0.0.1</version>
14<name>RurjsStarter</name>
15<description>Demo project for Spring Boot</description>
16
17<properties>
18<java.version>11</java.version>
19<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
20<security-jwt.version>1.0.9.RELEASE</security-jwt.version>
21<jjwt.version>0.9.0</jjwt.version>
22<spring-cloud-dependency-version>2.1.2.RELEASE</spring-cloud-dependency-version>
23</properties>
24
25<dependencies>
26<dependency>
27<groupId>org.springframework.boot</groupId>
28<artifactId>spring-boot-starter-web</artifactId>
29</dependency>
30<!--开发⼯具-->
31<dependency>
32<groupId>org.springframework.boot</groupId>
33<artifactId>spring-boot-devtools</artifactId>
34<scope>runtime</scope>
35<optional>true</optional>
36</dependency>
37<dependency>
38<groupId>org.apachemons</groupId>
39<artifactId>commons-lang3</artifactId>
40<version>3.9</version>
41</dependency>
42<!--lombok⼯具-->
43<dependency>
44<groupId>org.projectlombok</groupId>
45<artifactId>lombok</artifactId>
46<optional>true</optional>
47</dependency>
reactor spring48<!--单元测试-->
49<dependency>
50<groupId>org.springframework.boot</groupId>
51<artifactId>spring-boot-starter-test</artifactId>
52<scope>test</scope>
53<exclusions>
54<exclusion>
55<groupId>org.junit.vintage</groupId>
56<artifactId>junit-vintage-engine</artifactId>
57</exclusion>
58</exclusions>
59</dependency>
60<dependency>
61<groupId>io.projectreactor</groupId>
62<artifactId>reactor-test</artifactId>
63<scope>test</scope>
64</dependency>
65<!--jpa-redis-->
66<dependency>
67<groupId>org.springframework.boot</groupId>
68<artifactId>spring-boot-starter-data-jpa</artifactId>
69</dependency>
70<dependency>
71<groupId>mysql</groupId>
72<artifactId>mysql-connector-java</artifactId>
73<!--<version>5.1.46</version>-->
74</dependency>
75<dependency>
76<groupId>org.springframework.boot</groupId>
77<artifactId>spring-boot-starter-data-redis</artifactId>
78</dependency>
79<!--oauth2认证-->
80<dependency>
81<groupId>org..springframework.cloud</groupId>
82<artifactId>spring-cloud-starter-oauth2</artifactId>
83<version>${spring-cloud-dependency-version}</version>
84</dependency>
85<dependency>
86<groupId>org.springframework.cloud</groupId>
87<artifactId>spring-cloud-starter-security</artifactId>
88<version>${spring-cloud-dependency-version}</version>
89</dependency>
90<dependency>
91<groupId>org.springframework.security</groupId>
92<artifactId>spring-security-jwt</artifactId>
93<version>${security-jwt.version}</version>
94</dependency>
95<dependency>
96<groupId>io.jsonwebtoken</groupId>
97<artifactId>jjwt</artifactId>
98<version>0.7.0</version>
99</dependency>
100<!--json-->
101<dependency>
102<groupId>com.alibaba</groupId>
103<artifactId>fastjson</artifactId>
104<version>1.2.57</version>
105</dependency>
106<!--API⽂档-springfox-swagger2-->
107<dependency>
108<groupId>io.springfox</groupId>
109<artifactId>springfox-swagger2</artifactId>
110<version>2.9.2</version>
111<!--排除这个包,这⾥有个bug: Illegal DefaultValue  for parameter type integer-->
112<exclusions>
113<exclusion>
114<groupId>io.swagger</groupId>
115<artifactId>swagger-models</artifactId>
116</exclusion>
117</exclusions>
118</dependency>
119<dependency>
120<groupId>io.swagger</groupId>
121<artifactId>swagger-models</artifactId>
122<version>1.5.21</version>
123</dependency>
124<dependency>
125<groupId>io.springfox</groupId>
126<artifactId>springfox-swagger-ui</artifactId>
127<version>2.9.2</version>
128</dependency>
129</dependencies>
130
131<build>
132<plugins>
133<plugin>
134<groupId>org.springframework.boot</groupId>
135<artifactId>spring-boot-maven-plugin</artifactId>
136</plugin>
137</plugins>
138</build>
139
140</project>
2. l( 主要是 spring.datasource 和 spring.jpa部分)
1 server:
2  port: 9018
3 spring:
4  redis:
5    host: 127.0.0.1
6    database: 0
7  datasource:
8    url: jdbc:mysql://127.0.0.1:3306/rurjs_starter?characterEncoding=UTF-8&serverTimezone=UTC
9    username: root
10    password: DRsXT5sJ6Oi55LPj
11  jpa:
12    hibernate:
13      ddl-auto: update
14    database: mysql
15    show-sql: true
16    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
17
18 rjsSecurity:
19  exclude:
20    antMatchers: /oauth/**,/login,/home
21 #logging:
22 #  level: debug
3. 主类
1package com.rurjs.starter;
2
3import org.springframework.boot.SpringApplication;
4import org.springframework.boot.autoconfigure.SpringBootApplication;
5import org.springframework.web.bind.annotation.RequestMapping;
6import org.springframework.web.bind.annotation.RestController;
7
8 @SpringBootApplication
9public class RurjsStarterApplication {
10
11public static void main(String[] args) {
12        SpringApplication.run(RurjsStarterApplication.class, args);
13    }
14
15    @RestController
16public class HealthController{
17
18        @RequestMapping("ping")
19public String ping()
20        {
21return "Pong";
22        }
23    }
24 }
4. 实体类
package com.fig.sso.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.GrantedAuthority;
import org.springframework.security.oauth2.provider.ClientDetails;
import java.io.Serializable;
import javax.persistence.*;
import java.util.*;
@Getter
@Setter
@ToString
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table
public class OauthClientDetails implements Serializable{
private static final long serialVersionUID = 2930534157595467437L;
@Id
private String clientId;//client_id
@Fetch(FetchMode.JOIN)
@ElementCollection
private Set<String> resourceIds;//资源id
private String clientSecret;//client 密钥
}
⾃动⽣成表如下:
mysql> show create table oauth_client_details_resource_ids;
+-----------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| Table                            | Create Table                                                                                                                                                                                                                                                                                                      +-----------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| oauth_client_details_resource_ids | CREATE TABLE `oauth_client_details_resource_ids` (
`oauth_client_details_client_id` varchar(255) NOT NULL,
`resource_ids` varchar(255) DEFAULT NULL,
KEY `FKo1c1xapbgjtw5kgq9c1fy8vp3` (`oauth_client_details_client_id`),
CONSTRAINT `FKo1c1xapbgjtw5kgq9c1fy8vp3` FOREIGN KEY (`oauth_client_details_client_id`) REFERENCES `oauth_client_details` (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-----------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1 row in set (0.03 sec)
mysql>
5. Dao
package com.fig.sso.dao;
import com.fig.sso.domain.OauthClientDetails;
import org.springframework.pository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Collection;
@Repository("OauthClientDetailsDao")
public interface OauthClientDetailsDao extends JpaRepository<OauthClientDetails,String> {
//批量删除.
public int deleteAllByClientIdIn(Collection<String> clientId);
}
6. 单元测试
package com.rurjs.starter;
import com.fig.sso.dao.OauthClientDetailsDao;
import com.fig.sso.domain.OauthClientDetails;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.st.context.SpringBootTest;
import org.pto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import ansaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@SpringBootTest
class RurjsStarterApplicationTests {
@Autowired
private OauthClientDetailsDao oauthClientDetailsDao;
@Test
public void ClientInsert()
{
Set<String> resources = new HashSet<>();
resources.add("resource1");resources.add("all");
OauthClientDetails oauthClientDetails = new OauthClientDetails();
oauthClientDetails.setClientId("client1");
oauthClientDetails.setClientSecret("123456");
oauthClientDetails.setResourceIds(resources);
OauthClientDetails oauthClientDetails1 = oauthClientDetailsDao.save(oauthClientDetails);
System.out.println(oauthClientDetails1);
}
@Test
public void ClientQuery()
{
String clientId = "client1";
OauthClientDetails oauthClientDetails = oauthClientDetailsDao.findById(clientId).orElse(null);
System.out.println(oauthClientDetails);
}
}
7. 可能的⼀些问题及解决⽅式.
1. 添加数据(带⼀对多关系)时正常,但是查询的时候抛出异常如下
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.fig.sso.sourceIds, could not initialize proxy - no Session
at llection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
at llection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
at llection.adSize(AbstractPersistentCollection.java:162)
at llection.internal.PersistentSet.size(PersistentSet.java:168)
at java.base/java.util.HashSet.<init>(HashSet.java:119)
at com.fig.sso.ResourceIds(OauthClientDetails.java:66)
at com.fig.sso.String(OauthClientDetails.java:18)
at java.base/java.lang.String.valueOf(String.java:2951)
at java.base/java.io.PrintStream.println(PrintStream.java:897)
at com.rurjs.starter.RurjsStarterApplicationTests.ClientQuery(RurjsStarterApplicationTests.java:87)
at java.base/flect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/flect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/flect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/flect.Method.invoke(Method.java:566)
at org.junit.platformmons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
at org.ution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.ution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
at org.sion.TimeoutExtension.intercept(TimeoutExtension.java:132)
at org.sion.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
at org.sion.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
at org.ution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.ution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.ution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
at org.ution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
at org.ution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
at org.ution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
at org.ution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.ution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.ine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
at org.ine.support.ute(ThrowableCollector.java:73)
at org.ine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
at org.ine.ute(TestMethodTestDescriptor.java:135)
at org.ine.ute(TestMethodTestDescriptor.java:69)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.ine.support.ute(ThrowableCollector.java:73)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.ine.support.hierarchical.Node.around(Node.java:135)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.ine.support.ute(ThrowableCollector.java:73)
at org.ine.support.uteRecursively(NodeTestTask.java:122)
at org.ine.support.ute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.ine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.ine.support.ute(ThrowableCollector.java:73)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.ine.support.hierarchical.Node.around(Node.java:135)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.ine.support.ute(ThrowableCollector.java:73)
at org.ine.support.uteRecursively(NodeTestTask.java:122)
at org.ine.support.ute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.ine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.ine.support.ute(ThrowableCollector.java:73)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.ine.support.hierarchical.Node.around(Node.java:135)
at org.ine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.ine.support.ute(ThrowableCollector.java:73)
at org.ine.support.uteRecursively(NodeTestTask.java:122)
at org.ine.support.ute(NodeTestTask.java:80)
at org.ine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.ine.support.ute(HierarchicalTestExecutor.java:57)
at org.ine.support.ute(HierarchicalTestEngine.java:51)
at org.junit.ute(DefaultLauncher.java:229)
at org.junit.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.ute(DefaultLauncher.java:191)
at org.junit.ute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
at cution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at cution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at cution.junit.JUnitStarter.main(JUnitStarter.java:70)
解决⽅式:在实体类中给有⼀对多关系的属性(如 resourceIds )上添加注解 @Fetch(FetchMode.JOIN);⽆该注解和注解为 @Fetch(FetchMode.SUBSELECT)或@Fetch(FetchMode.SELECT)时,都会抛出该异常,按异常信息来说,解决懒加载问题也⾏,题主未并未使⽤解决懒加载的⽅式解决该异常。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。