我已经尝试了很多来解决这个问题。阅读带有hibernate文档的spring data jpa参考文档,但在这种情况下没有运气。 在github上发现spring数据jpa的例子太短了,文档对像我这样的新手来说不是很有帮助。
我有以下情况: 我的项目是在spring boot中使用存储库层中的spring-data-jpa。 投资可以是FixedDepositInvestment,RecurringDepositInvestment或任何其他子类型。为此,我在hibernate中使用了继承。
注意:省略了getter和setter。 问题可能很冗长
BaseEntity类
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer id;
}
投资类
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Investment extends BaseEntity{
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Temporal(TemporalType.DATE)
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Column(name = "issue_date", nullable = true)
private Date dateOfIssue;
@CreationTimestamp
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Column(name = "dateCreated")
private Date dateCreated;
@UpdateTimestamp
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Column(name = "lastUpdated")
private Date lastUpdated;
}
CertificateInvestment class
@MappedSuperclass
public abstract class CertificateInvestment extends Investment {
public CertificateInvestment() {
}
public CertificateInvestment(User user, int amountInvested) {
super(user);
this.amountInvested = amountInvested;
}
@Column(name = "amount_invested", nullable = false)
private int amountInvested;
@Column(name = "account_no", nullable = true) // can be folio no or any other name
private String accountNo;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "investment_id", nullable = true)
List<Nominee> nominees;
}
BankCertificateInvestment class
@MappedSuperclass
public abstract class BankCertificateInvestment extends CertificateInvestment{
public BankCertificateInvestment() {
super();
}
public BankCertificateInvestment(User user, int amountInvested, Bank bank) {
super(user, amountInvested);
this.bank = bank;
}
@OneToOne
@JoinColumn(name = "bank_id", nullable = false)
private Bank bank;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "investment_id", nullable = true) //???
private Set<JointHolder> accountJointHolders; // make sure same jh is not added again
@Temporal(TemporalType.DATE)
@DateTimeFormat(pattern="yyyy-MM-dd")
@Column(name = "maturity_date", nullable = true)
private Date dateOfMaturity;
@Column(name = "interest_rate", nullable = true)
private float interestRate;
@Enumerated(EnumType.STRING)
@Column(nullable = true)
private InterestPayable interestPayable;
@Column(nullable = true)
private int durationInMonths;
}
FixedDepositInvestment类
@Entity
@PrimaryKeyJoinColumn(name = "id")
@Table(name = "FixedDepositInvestment")
public class FixedDepositInvestment extends BankCertificateInvestment {
public FixedDepositInvestment() {
super();
}
public FixedDepositInvestment(User user, int amountInvested, Bank bank) {
super(user,amountInvested, bank);
}
@Column(nullable = true)
private String creditToAccountNumber;
}
为此,我创建了以下存储库接口:
InvestmentRepository接口:
@Transactional(readOnly = true)
public interface InvestmentRepository extends CrudRepository<Investment, Integer> {
}
FixedDepositInvestmentRepository接口:
@Transactional
public interface FixedDepositInvestmentRepository extends CrudRepository<FixedDepositInvestment, Integer> {
}
UserRepository接口:
@Transactional(readOnly = true)
public interface UserRepository extends CrudRepository<User, Integer> {
}
BankRepository接口:
public interface BankRepository extends CrudRepository<Bank,Integer>{
}
最后,我执行了以下代码
注意:我在控制器@RequestMapping
方法中直接编写代码仅用于测试目的。
@Controller
public class AddInvestmentController {
@Autowired
FixedDepositInvestmentRepository fixedDepositInvestmentRepo;
@Autowired
UserRepository userRepository;
@Autowired
BankRepository bankRepository;
@Autowired
EntityManager em;
@RequestMapping(value = "/addme", method = RequestMethod.GET)
public String addInvestment() {
User user = new User("Oliver","Gierke","9999999999",new Date(),"123456");
Bank bank = new Bank("tjsb","123456");
userRepository.save(user);
bankRepository.save(bank);
FixedDepositInvestment fd = new FixedDepositInvestment(user, 1000, bank);
fixedDepositInvestmentRepo.save(fd);
fd.setAccountNo("55555");
fd.setAmountInvested(12345);
fd.setAmountInvested(352);
System.out.println("date created : -------------" + fd.getDateCreated() + " " + fd.getLastUpdated());
// System.out.println(fixedDepositInvestmentRepo.findAll());
return "add";
}
}
被解雇的查询是:
Hibernate:
insert
into
User
(address, dob, firstName, lastName, mobile, user_password)
values
(?, ?, ?, ?, ?, ?)
Hibernate:
insert
into
Bank
(address, name, ifsc_code)
values
(?, ?, ?)
Hibernate:
insert
into
Investment
(dateCreated, issue_date, lastUpdated, user_id)
values
(?, ?, ?, ?)
Hibernate:
insert
into
FixedDepositInvestment
(account_no, amount_invested, amount_on_maturity, bank_id, maturity_date, durationInMonths, interestPayable, interest_rate, creditToAccountNumber, id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
恼人的部分是线
fd.setAccountNo("55555");
fd.setAmountInvested(12345);
fd.setAmountInvested(352);
不要点击UPDATE查询。所以,我的lastUpdated日期与dateCreated相同。
但是,如果我打电话
System.out.println(fixedDepositInvestmentRepo.findAll());
它会触发UPDATE然后选择 同样的事情也发生在测试用例中。 使用相同的代码,如果我添加
@Autowired
TestEntityManager em;
and
em.flush()
// at method ending, the update is called.
这种行为很烦人,这给我提出了很多问题:
repository.save(entity)
来更新更改?@Transactional
使用readOnly=true
。 @NoRepositoryBean
定义@MappedsuperClass
?我在一些帖子中看到,人们创建这些,我不知道是否需要,在什么情况下我应该为这些类创建norepositorybean?