【发布时间】:2021-01-19 19:16:00
【问题描述】:
注意:我使用 Spring Data Jpa 进行持久化。
问题:
我有两个模型:User 和 Badge
我有一个用户拥有的徽章列表作为 User 类中的数据成员。 我还有用户作为 徽章 类中的数据成员(即徽章的创建者)
我想在用户和徽章数据成员列表之间建立关系。 关系是 OneToMany 类型(即一个用户将拥有许多徽章),反之亦然。
我希望它以这种方式工作, 在代码中,
当我将颁发者(又名用户)设置为特定用户对象的徽章对象保存时,无需将其(徽章)添加到用户拥有的徽章列表中。
我已尝试创建关系,但它在 REST API 响应中返回用户拥有的徽章的空列表。
徽章模型
import javax.persistence.*;
@Entity
@Table(name = "badges")
public class Badge {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "badge_id")
private int mId;
@Column(name = "badge_name" , nullable = false , unique = true)
private String mName;
@Column(name = "badge_description")
private String mDescription;
@Lob
@Column(name = "badge_logo" , nullable = false)
private String mLogo;
@ManyToOne
@JoinColumn(name = "issuer_id")
private User mIssuer;
}
用户模型
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "users")
public class User {
@Id@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id")
private long mId;
@Column(name = "username" , nullable = false , unique = true)
private String mUserName;
@Column(name = "fullname",nullable = false)
private String mFullName;
@Column(name = "salt")
private String mSalt;
@OneToMany(mappedBy = "mIssuer",cascade = CascadeType.ALL)
private List<Badge> mOwnedBadges;
@OneToMany
@JoinColumn(name = "received_badges_id")
private List<Badge> mReceivedBadges;
}
CommandLineRunner
import com.badging.spinnerbadger.SpinnerBadger.Models.Badge;
import com.badging.spinnerbadger.SpinnerBadger.Models.User;
import com.badging.spinnerbadger.SpinnerBadger.Services.Intefaces.BadgeSerivce;
import com.badging.spinnerbadger.SpinnerBadger.Services.Intefaces.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class StartupExecutor implements CommandLineRunner {
@Autowired
private BadgeSerivce mBadgeSerivce;
@Autowired
private UserService mUserService;
@Override
public void run(String... args) throws Exception {
//TODO:: issuer cannot issue badge to itself
final User user1 = new User();
user1.setFullName("User1 FullName");
user1.setSalt("salt1");
user1.setUserName("User1 UserName");
mUserService.save(user1);
final User user2 = new User();
user2.setFullName("User2 FullName");
user2.setSalt("salt2");
user2.setUserName("User2 UserName");
mUserService.save(user2);
Badge badge1 = new Badge();
badge1.setDescription("Desc1");
badge1.setLogo("Logo1");
badge1.setName("Badge1");
badge1.setIssuer(user1);
mBadgeSerivce.save(badge1);
Badge badge2 = new Badge();
badge2.setDescription("Desc2");
badge2.setLogo("Logo2");
badge2.setName("Badge2");
badge2.setIssuer(user2);
mBadgeSerivce.save(badge2);
Badge badge3 = new Badge();
badge3.setDescription("Desc3");
badge3.setLogo("Logo3");
badge3.setName("Badge3");
badge3.setIssuer(user1);
mBadgeSerivce.save(badge3);
user1.setReceivedBadges(Arrays.asList(badge2));
user2.setReceivedBadges(Arrays.asList(badge1,badge3));
}
}
注意:它也不会保存用户收到的徽章列表,如果你也能弄清楚,那我真的很感激你。
徽章回购
import com.badging.spinnerbadger.SpinnerBadger.Models.Badge;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BadgeRepo extends PagingAndSortingRepository<Badge,Long> {
}
用户回购
import com.badging.spinnerbadger.SpinnerBadger.Models.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepo extends JpaRepository<User,Long> {
}
BadgeServiceImpl
package com.badging.spinnerbadger.SpinnerBadger.Services.Implentations;
import com.badging.spinnerbadger.SpinnerBadger.Repository.BadgeRepo;
import com.badging.spinnerbadger.SpinnerBadger.Models.Badge;
import com.badging.spinnerbadger.SpinnerBadger.Services.Intefaces.BadgeSerivce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class BadgeServiceImpl implements BadgeSerivce {
@Autowired
private BadgeRepo mBadgeRepo;
@Override
public List<Badge> getAllBadges(int pageNumber , int sizeOfPage) {
if (sizeOfPage > 20) {
sizeOfPage = 20;
}
final Page<Badge> allPages = mBadgeRepo.findAll(PageRequest.of(pageNumber,
sizeOfPage));
if (allPages.getTotalElements() > 0) {
return allPages.toList();
} else{
return new ArrayList<Badge>();
}
}
@Override
public void save(Badge badge) {
mBadgeRepo.save(badge);
}
}
UserServiceImpl
import com.badging.spinnerbadger.SpinnerBadger.Models.Badge;
import com.badging.spinnerbadger.SpinnerBadger.Models.User;
import com.badging.spinnerbadger.SpinnerBadger.Repository.UserRepo;
import com.badging.spinnerbadger.SpinnerBadger.Services.Intefaces.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepo mUserRepo;
@Override
public void save(User user) {
mUserRepo.save(user);
}
@Override
public List<Badge> getUsersReceivedBadgeList(long userId) {
final Optional<User> byId = mUserRepo.findById(userId);
return byId.orElse(new User()).getReceivedBadges();
}
@Override
public List<Badge> getUserOwnedBadgeList(long userId) {
final Optional<User> byId = mUserRepo.findById(userId);
return byId.orElse(new User()).getReceivedBadges();
}
}
由 Hibernate 生成的 SQL -> 用户模型第 1 名,徽章模型第 2 名
Hibernate: insert into users (fullname, salt, username, user_id) values (?, ?, ?, ?)
Hibernate: insert into badges (badge_description, issuer_id, badge_logo, badge_name, badge_id) values (?, ?, ?, ?, ?)
【问题讨论】:
-
你在
commit之后刷新你的更改吗? -
我觉得缺少一些有助于回答这个问题的东西。首先,不清楚 BadgeService 和 UserServiced 是如何实现的。在我的测试应用程序中,我为它们创建了扩展 JpaRepository 的接口。其次,我不遵循 mReceivedBadges 的映射方式。看着它,我觉得应该有另一个表和实体。在我的示例应用程序中。我无法让这部分按原样运行并将其排除在外。通过这两项更改,我能够在此函数中创建数据,然后在 REST 端点中检索具有自有徽章的用户。
-
@Vishrant 不,我没有刷新甚至提交,我正在使用 JpaRepository 的保存方法()来保存实体。
-
@darrendanvers BadgeService 和 UserService 分别抽象出 BadgeRepo(inteface) 和 UserRepo(inteface) 的操作。两个 Repo 接口都扩展了 JpaRepository。 我已将代码添加到帖子中,请参考那里。
-
@darrendanvers 对于第二点,我也知道关系存在一些问题,我想我需要添加两个单独的实体,一个应该是 DisplayableBadge 和RecievableBadge ,就像前者必须有拥有该对象的用户对象,后者必须有一个用户对象,他是徽章的接收者,并且必须有一个所有者(也就是创建它的人)用户对象。我想对了吗? ,尽管我的首要任务是首先获取所有者列表。
标签: spring-boot hibernate spring-data-jpa hibernate-mapping