java Spring数据JPA不会在脏上下文上触发更新查询
为了解决这个问题,我做了很多努力。阅读spring data jpa参考文档和hibernate文档,但在这种情况下运气不佳。 发现github上的spring data jpa示例太短,而且文档对我这样的新手帮助不大
我有以下情况: 我的项目在spring boot中,spring data jpa位于存储库层。 投资可以是固定存款投资、定期存款投资或任何其他子类型。为此,我在hibernate中使用了继承
注:省略了getter和setter。 这个问题可能很长
BaseEntity class
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer id;
}
Investment class
@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 class
@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 interface:
@Transactional(readOnly = true)
public interface InvestmentRepository extends CrudRepository<Investment, Integer> {
}
FixedDepositInvestmentRepository interface :
@Transactional
public interface FixedDepositInvestmentRepository extends CrudRepository<FixedDepositInvestment, Integer> {
}
UserRepository interface :
@Transactional(readOnly = true)
public interface UserRepository extends CrudRepository<User, Integer> {
}
银行存储库界面:
public interface BankRepository extends CrudRepository<Bank,Integer>{
}
最后,我执行了以下代码
注意:我直接在controller @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);
根本不启动更新查询。所以,我上次更新的日期与dateCreated相同
然而,如果我打电话
System.out.println(fixedDepositInvestmentRepo.findAll());
它触发一个更新,然后选择 同样的事情也发生在测试用例中。 使用相同的代码,如果我添加
@Autowired
TestEntityManager em;
and
em.flush()
// at method ending, the update is called.
这种行为很烦人,这给我提出了很多问题:
- 为什么不调用更新?Spring data jpa不检查脏上下文,我们是否需要再次触发
repository.save(entity)
来更新更改李> - 在spring jpa文档中提到,当您将事务配置为只读时,会导致Hibernate跳过脏检查(这是对大型对象树的显著改进)。
现在我不知道我是否应该把
@Transactional
和readOnly=true
一起使用李> - 我是否也需要为所有
@MappedsuperClass
定义@NoRepositoryBean
?我在一些帖子中看到,人们创建了这些,我不知道是否需要,在什么情况下我应该为这些类创建norepositorybean李> - 我是否以正确的格式调用了查询(方法)李>
- 这是hibernate还是spring数据jpa的问题李>
- 我们什么时候需要TestEntityManager?我们使用spring数据jpa时需要它吗李>
共 (0) 个答案