有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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.

这种行为很烦人,这给我提出了很多问题:

  1. 为什么不调用更新?Spring data jpa不检查脏上下文,我们是否需要再次触发repository.save(entity)来更新更改
  2. 在spring jpa文档中提到,当您将事务配置为只读时,会导致Hibernate跳过脏检查(这是对大型对象树的显著改进)look at。 现在我不知道我是否应该把@TransactionalreadOnly=true一起使用
  3. 我是否也需要为所有@MappedsuperClass定义@NoRepositoryBean?我在一些帖子中看到,人们创建了这些,我不知道是否需要,在什么情况下我应该为这些类创建norepositorybean
  4. 我是否以正确的格式调用了查询(方法)
  5. 这是hibernate还是spring数据jpa的问题
  6. 我们什么时候需要TestEntityManager?我们使用spring数据jpa时需要它吗

共 (0) 个答案