Jpa 空值 序列化 错误

这篇博客主要介绍了如何使用Jackson库在实体类中忽略特定属性,包括在父类中统一配置,以及在YAML配置文件中设置对象序列化选项。同时,展示了配置类`JacksonConfig`中对`ObjectMapper`的定制,包括处理未知属性、控制特殊字符和单引号的显示,并将null值转换为空字符串。

在这里插入图片描述

1. 实体类 加 @JsonIgnoreProperties({“hibernateLazyInitializer”,“handler”})
2. 如果觉得每个实体类添加麻烦,则在公共父类添加
@JsonIgnoreProperties(ignoreUnknown = true, value = {"hibernateLazyInitializer", "handler", "fieldHandler"})

在这里插入图片描述

2.yml 配置
# Spring 配置
spring:
  jackson:
    default-property-inclusion: NON_EMPTY
    #deserialization:
      #允许对象忽略json中不存在的属性
      #fail_on_unknown_properties: true
spring:
  jackson:
    #default-property-inclusion: NON_EMPTY
    deserialization:
      #允许对象忽略json中不存在的属性
      #fail_on_unknown_properties: true
      FAIL_ON_IGNORED_PROPERTIES: true
3.配置类
@Configuration
public class JacksonConfig {

    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
    {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();

        // 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化
        // Include.Include.ALWAYS 默认
        // Include.NON_DEFAULT 属性为默认值不序列化
        // Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量
        // Include.NON_NULL 属性为NULL 不序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 允许出现特殊字符和转义符
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        // 允许出现单引号
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        // 字段保留,将null值转为""
        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                jsonGenerator.writeString("");
            }
        });
        return objectMapper;
    }
}
<think>好的,用户问的是实体类报空指针错误,这个问题在Java开发中挺常见的,我需要先理清楚可能的原因和解决方法。首先,空指针异常通常是因为调用了某个对象的方法或属性,但这个对象是null。 用户提到的是实体类,可能是在使用类似Hibernate或者MyBatis这样的ORM框架时出现的。首先,我需要考虑实体类本身是否被正确初始化。比如,当从数据库查询数据时,如果没有找到对应的记录,返回的实体类对象可能就是null,这时候如果直接访问它的属性就会报错。这时候应该检查查询结果是否为null,并做相应的处理。 接下来,用户可能在代码中直接使用了实体类的getter方法,而没有先检查对象是否为空。比如,user.getName(),如果user是null,就会抛出空指针。这时候应该在使用前先判断if(user != null)。 另外,实体类中的某些属性可能没有被正确初始化。例如,实体类中的集合属性,如List,如果没有初始化,直接调用add方法也会导致空指针。这时候应该在声明的时候初始化,比如private List<String> items = new ArrayList<>();。 还有可能是在使用链式调用时,中间的某个对象为null。比如user.getAddress().getCity(),如果address是null,这里就会出错。这时候需要逐个检查每个对象是否为空,或者使用Optional类来避免深层嵌套的null检查。 另外,自动装配的问题也可能导致空指针。比如,使用Spring的@Autowired注解时,如果依赖注入失败,对象为null。这时候需要检查Spring的配置是否正确,或者是否漏掉了@Service、@Repository等注解。 还有可能是在实体类被反序列化的时候,比如从JSON转换过来,某些字段没有被正确赋值,导致为null。这时候需要检查反序列化的过程,或者使用构造方法或Builder模式来确保所有必要字段都被初始化。 用户可能需要具体的代码示例,比如如何正确初始化对象,如何使用Optional,或者如何添加空检查。此外,可能还需要提醒他们在开发过程中使用工具,比如IDE的断点调试,或者静态代码分析工具来检测潜在的空指针问题。 还要考虑用户的使用场景,可能是刚接触Java的新手,或者是正在处理一个复杂的项目,需要定位问题。可能需要分步骤解释,如何逐步排查空指针的原因,比如查看异常堆栈信息,找到具体的行号,检查该行的对象是否可能为null。 总结来说,回答需要涵盖常见的空指针原因,如对象未初始化、方法调用链中的null、依赖注入失败、集合未初始化等,并提供相应的解决方法和代码示例。同时,给出调试和预防的建议,比如使用Optional、断言、静态分析工具等,帮助用户从根本上减少空指针的发生。</think>以下是关于 **实体类空指针错误(NullPointerException)** 的详细解析与解决方案: --- ### 一、错误本质 空指针异常(`NullPointerException`,简称NPE)的本质是:**试图访问或操作一个未初始化(值为`null`)的对象引用**。 在实体类场景中,通常发生在以下位置: ```java user.getName(); // user为null list.add(data); // list未初始化 obj.getX().getY(); // obj或getX()返回null ``` --- ### 二、常见场景与解决方案 #### 场景1:实体类对象未初始化 **错误代码**: ```java User user; // 未初始化 System.out.println(user.getName()); ``` **修复方法**: ```java // 明确初始化 User user = new User(); // 或延迟初始化(需判空) if (user != null) { System.out.println(user.getName()); } ``` --- #### 场景2:级联调用中的null值 **错误代码**: ```java String city = order.getUser().getAddress().getCity(); ``` **修复方法**: ```java // 逐级判空 if (order != null && order.getUser() != null && order.getUser().getAddress() != null) { String city = order.getUser().getAddress().getCity(); } // 或使用Java 8 Optional String city = Optional.ofNullable(order) .map(Order::getUser) .map(User::getAddress) .map(Address::getCity) .orElse("未知"); ``` --- #### 场景3:集合属性未初始化 **错误代码**: ```java public class Order { private List<Item> items; // 未初始化 public void addItem(Item item) { items.add(item); // 抛出NPE } } ``` **修复方法**: ```java // 在声明时或构造函数中初始化 private List<Item> items = new ArrayList<>(); ``` --- #### 场景4:自动注入失败 **错误代码**: ```java @Service public class UserService { @Autowired private UserDao userDao; // 若未注入成功 public void save(User user) { userDao.save(user); // userDao为null时抛出NPE } } ``` **修复方法**: 1. 检查Spring配置(扫描路径、依赖包) 2. 使用构造函数注入替代字段注入: ```java private final UserDao userDao; @Autowired public UserService(UserDao userDao) { this.userDao = userDao; } ``` --- ### 三、调试与定位技巧 1. **查看堆栈信息** 异常信息会明确提示NPE发生的代码行号: ``` java.lang.NullPointerException: null at com.example.MyClass.method(MyClass.java:25) ``` 2. **使用断点调试** 在可疑位置设置断点,观察变量状态(IDEA/Eclipse调试模式)。 3. **防御性编程** 在关键位置添加断言: ```java Objects.requireNonNull(obj, "对象不能为null"); ``` --- ### 四、预防策略 | 措施 | 说明 | |-----------------------|--------------------------------------------------------------------| | **初始化默认值** | 实体类集合属性在声明时初始化(`new ArrayList<>()`) | | **使用Optional** | Java 8+ 使用Optional包装可能为null的返回值 | | **Lombok @NonNull** | 结合Lombok自动生成空值检查代码 | | **静态代码分析** | 使用SpotBugs、SonarQube等工具检测潜在NPE | | **单元测试覆盖** | 编写测试用例覆盖null输入场景 | --- ### 五、典型代码对比 **危险写法**: ```java public void process(User user) { String name = user.getName().toUpperCase(); // 两级潜在NPE } ``` **安全写法**: ```java public void process(User user) { if (user != null && user.getName() != null) { String name = user.getName().toUpperCase(); } // 或 Optional.ofNullable(user) .map(User::getName) .ifPresent(name -> System.out.println(name.toUpperCase())); } ``` --- ### 六、框架相关注意点 1. **MyBatis查询结果** 当数据库查询无结果时,返回的实体类对象为`null`: ```java User user = userMapper.selectById(999); // 需判空 ``` 2. **JSON反序列化** 确保反序列化的JSON包含所有必要字段(如使用`@JsonInclude`注解)。 3. **JPA延迟加载** 在事务外访问`@OneToMany`等延迟加载属性会抛出`LazyInitializationException`。 --- **总结**: 空指针错误的根本解决之道在于 **严谨的代码习惯** + **防御性编程** + **工具辅助**。通过合理的设计和规范的代码审查,可以显著降低NPE发生率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值