java - Spring Messaging 和 GsonMessageConverter 的 LazyInitializationException

标签 java spring spring-session spring-messaging

我正在使用Spring BootSpring MessagingGson用于 websocket 连接并向客户端发送消息。现在我面临LazyInitializationException将新字段添加到我的模型并将其发送给客户端后出错。

这是我的模型类:

@Entity
public class Vehicle {
    @Expose
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Expose
    private String name;

    //...
    //some other simple fields
    //...

    @Expose
    @ElementCollection(fetch = FetchType.LAZY)
    @CollectionTable(name = "vehicle_property_values", joinColumns = @JoinColumn(name = "vehicle_id"))
    @MapKeyColumn(name = "key")
    @Column(name="value")
    private Map<String, String> properties = new HashMap<>();
}

我正在使用GsonMessageConverter将对象转换为 json 并从 https://github.com/Coding/WebIDE-Backend/blob/master/src/main/java/net/coding/ide/web/message/GsonMessageConverter.java 发送到客户端

转换器工作正常,但最近我添加了 Map<String, String> properties给我的Vehicle模型,并且有问题。我遇到异常:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.test.vehicles.model.Vehicle.properties, could not initialize proxy - no Session

GsonMessageConverter 的第 105 行

this.gson.toJson(payload, writer);

以下是我在 Service 类中发送消息的方式:

@Service
@Transactional
class VehicleServiceImpl implements VehicleService {
    @Autowired
    VehicleRepository vehicleRepository; //JpaRepository
    @Autowired
    SimpMessagingTemplate simpMessagingTemplate;

    private final ConcurrentLinkedDeque<Vehicle> pendingVehicles = new ConcurrentLinkedDeque<>(); 

    //..some other fields and methods irrelevant in this case

    //method called from controller
    @Override
    void addPendingVehicle(Vehicle vehicle) {
        //set some variables in vehicle
        vehicle = vehicleRepository.save(vehicle);
        pendingVehicles.add(vehicle);
    }

    @Scheduled(initialDelay = 60000, fixedRate = 60000)
    @Transactional
    void sendPendingVehicles() {
        if(pendingVehicles.size() > 0) {
            simpMessagingTemplate.convertAndSend("/topic/vehicles", pendingVehicles);
            pendingVehicles.clear();
        }
    }
}

这是我的 WebSocket 配置(仅非空方法):

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/queue", "/topic");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/testapp").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public boolean configureMessageConverters(List<MessageConverter> converters) {
        Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
        converters.add(new GsonMessageConverter().setGson(gson));
        return true;
    }
}

我不知道如何解决它。如何使其成为事务性的?

最佳答案

我不需要在 websocket 消息中发送属性,因此我创建了注释

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcludeWebSocketSerialization { }

并将 ExclusionStrategy 添加到我的 Gson

.addSerializationExclusionStrategy(new ExclusionStrategy() {
    @Override
    public boolean shouldSkipField(FieldAttributes fieldAttributes) {
    return fieldAttributes.getAnnotation(ExcludeWebSocketSerialization.class) != null;
    }

    @Override
    public boolean shouldSkipClass(Class<?> aClass) {
    return false;
    }
})

关于java - Spring Messaging 和 GsonMessageConverter 的 LazyInitializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45919607/

相关文章:

java - 使用 imageJ 查找边缘数组

Java:try-with-resources 与 try-catch-finally 关于自动关闭的顺序

java - 考虑在您的配置中定义类型为 'redis.clients.jedis.JedisPool' 的 bean。集成Redis Jedis时出错

java - 如何在 Spring AuthenticationSuccessHandler 实现中注入(inject)原型(prototype) bean

spring-boot - 如何在 Redis 连接失败时绕过 Spring Boot 应用程序上的 Redis session ?

spring-boot - 如何使 Spring session 在多个请求中保持不变?

spring-boot - 在没有 Spring Security 的情况下保留 Spring session

java - POI 货币问题

java - 无法让 JApplet 工作。每次运行该程序时都会出现错误

java - Spring log4j 无法在 osx 上保存日志文件