Spring Data JPA不会在脏上下文

时间:2017-01-19 17:07:42

标签: java hibernate spring-boot spring-data-jpa

我已经尝试了很多来解决这个问题。阅读带有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.

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

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

0 个答案:

没有答案