打印多对多实体时出现异常
Posted
技术标签:
【中文标题】打印多对多实体时出现异常【英文标题】:Exception when printing out ManyToMany entity 【发布时间】:2022-01-23 18:16:14 【问题描述】:我正在创建一个使用 Spring Data JPA 学习的简单项目。
我有这个实体(为清楚起见删除了 getter/setter):
@Entity
@Table(name = "shop")
@JsonIgnoreProperties("barbers")
public class Shop
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "idshop")
private int shopID;
@Column(name = "name")
private String name;
@Column(name = "address")
private String address;
//THIS SHOWS HOW MANY BARBERS WORKS IN THIS SHOP - CHILD
@ManyToMany(mappedBy = "shops", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, CascadeType.MERGE)
private Set<Barber> barbers = new LinkedHashSet<>();
public Set<Barber> getBarbers()
return barbers;
public void removeBarber(Barber barber)
barbers.remove(barber);
barber.getShops().remove(this);
public void addBarber(Barber barber)
barbers.add(barber);
barber.getShops().add(this);
public Shop()
public Shop(String name, String address)
this.name = name;
this.address = address;
this.address = address;
@Override
public String toString()
return "Shop" +
"id=" + shopID +
", name='" + name + '\'' +
", address='" + address + '\'' +
", barbers='" + barbers + '\'' +
'';
我有一个简单的控制器,它可以很好地从存储库中获取请求的商店并将其返回。当我执行 System.out.println() 时,我可以看到以下内容:Shopid=3, name='fade', address='hammersmith', barbers='[Barberid=1, name='bob', rating='4']'
但是当控制器返回对象时,我得到以下异常:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.gogobarber.barber.entities.Shop$HibernateProxy$U83qWd1X["hibernateLazyInitializer"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.13.0.jar:2.13.0]
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1300) ~[jackson-databind-2.13.0.jar:2.13.0]
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400) ~[jackson-databind-2.13.0.jar:2.13.0]
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:46) ~[jackson-databind-2.13.0.jar:2.13.0]
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:29) ~[jackson-databind-2.13.0.jar:2.13.0]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.13.0.jar:2.13.0]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774) ~[jackson-databind-2.13.0.jar:2.13.0]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.13.0.jar:2.13.0]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~[jackson-databind-2.13.0.jar:2.13.0]
我有一个好主意,错误源于将 pojo 编组为 json 字符串,并且错误的原因很可能来自 Set<Barber>
(尽管错误谈论没有找到 byteBuddy 的序列化程序.. 这是什么?)。通常总是配置杰克逊对象映射器吗?我假设杰克逊应该足够先进来解决一个集合?也许是因为我配置多对多关系的方式?
EDIT = 这是我的控制器和理发师课程:
@Entity
@Table(name = "barber")
@JsonIgnoreProperties("shops")
public class Barber
public Barber()
public Barber(String name, String rating)
this.name = name;
this.rating = rating;
public int getBarberId()
return barberId;
public String getName()
return name;
public void setName(String name)
this.name = name;
public String getRating()
return rating;
public void setRating(String rating)
this.rating = rating;
public Set<Shop> getShops()
return shops;
//THIS FETCHES THE SHOPS THE BARBER IS ASSOCAITED TO - PARENT
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, CascadeType.MERGE)
@JoinTable(name = "barberworkinshops",
joinColumns = @JoinColumn(name = "Barber_ID", referencedColumnName = "idbarber"),
inverseJoinColumns = @JoinColumn(name = "Shop_ID", referencedColumnName = "idshop")
)
private Set<Shop> shops = new LinkedHashSet<>();;
public void addBarberToShop(Shop shop)
shops.add(shop);
shop.getBarbers().add(this);
public void removeBarberFromShop(Shop shop)
shops.remove(shop);
shop.getBarbers().remove(this);
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "idbarber")
private int barberId;
@Column(name = "Name")
private String name;
@Column(name = "Rating")
private String rating;
@Override
public String toString()
return "Barber" +
"id=" + barberId +
", name='" + name + '\'' +
", rating='" + rating + '\'' +
", shops='" + shops + '\'' +
'';
控制器:
@RestController
public class ShopController
@Autowired
private BarberRepo barberRepo;
@Autowired
private ShopRepo shopRepo;
@GetMapping("/shop/id")
public Shop getShop(@PathVariable String id)
Shop shop = shopRepo.getById(Integer.valueOf(id));
System.out.println(shop);
return shop;
@PostMapping("/shop/name/address")
public Shop createShop(@PathVariable String name, @PathVariable String address)
Shop shop = new Shop(name, address);
return shopRepo.save(shop);
@PatchMapping("/shop/sId/addBarber/bId")
public Shop addBarber(@PathVariable String sId, @PathVariable String bId)
Shop shop = shopRepo.getById(Integer.valueOf(sId));
Barber b = barberRepo.getById(Integer.parseInt(bId));
shop.addBarber(b);
Shop save = shopRepo.save(shop);
return save;
【问题讨论】:
尝试在 Set据我所知,您在 Shop 实体中使用延迟加载来收集理发师...
如果从事务中取出或者通过jackson序列化可能会有问题...
我建议你可以做一些事情来避免控制台日志中的错误。
1- 在服务中加载理发师收藏,我个人想创建更多的服务层来与 DB Repo 层交互,你可以创建 ShopService 来管理它,你可以通过简单的方法强制加载: shop.getBarbers().size(); // 强制在同一个事务中获取实体
2- 为每个实体添加@JsonIgnoreProperties("hibernateLazyInitializer", "handler")
@JsonIgnoreProperties("hibernateLazyInitializer", "handler")
3- 设置 jackson 选项 fail-on-empty-beans=false。
spring.jackson.serialization.fail-on-empty-beans=false
或
ObjectMapper objectMapper = new ObjectMapper();
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
【讨论】:
以上是关于打印多对多实体时出现异常的主要内容,如果未能解决你的问题,请参考以下文章