关联实体未保存在事务中

Associated Entity does not get saved in transaction

我对实体框架还很陌生,不明白为什么我的实体没有被正确保存。

编辑:

我会尽快尝试出这个测试代码,看看它是否有效:

@Transactional
public void doConvert(String lakoKod) {
    LsZFutelszHavi futelszHavi = new LsZFutelszHavi();
    //Give it values like:
    futelszHavi.setOrigKorrOssz(new BigDecimal(500));
    LsTLako lako = lsTLakoRepository.findOneByLakoKod(lakoKod);
    LsZFutelsz futelsz = lsZFutelszRepository.findOneByLsTLako(lako);
    //The modification which not get saved into tha Firebird table in the original code. Will it be saved now?
    futelsz.setSzezVegenBefOssz(new BigDecimal(100));
    futelszHavi.setLsZFutelsz(futelsz);
    lsZFutelszHaviRepository.save(futelszHavi);
}

我正在尝试从旧的 DBASE 数据库转换为 Firebird 数据库。 Firebird 数据库有它的 tables 由实体映射。我读了一个DBASEtable,然后逐行转换。

我使用@Transactional 来保存 DBASE table 的所有转换实体,或者保存 none。

我设法将每个 table 正确转换到新数据库中,只有一个除外。

在其他 table 中,我只需为每条记录保存一个实体,而不必修改其他类型的实体。我通常必须创建一个 X 型实体,将它连接到一个 Y 型实体,然后保存。为了保存,我为实体使用了一个存储库(如果重要的话 org.springframework.data.repository.PagingAndSortingRepository)

在那个特定的 DBASE table 中,我必须创建一个 A 类实体,将它连接到 B 类实体,修改 B 类实体,然后保存。问题是,B 类实体修改没有保存到 Firebird table。同样,我使用存储库来保存实体。

要获取 B 类实体,我使用它的存储库方法:

LsZFutelsz findOneByLsTLako(LsTLako lsTLako); 

我猜想,如果我用它自己的存储库保存这个 B 型实体,它会在数据库中正确修改。没用。

如果需要更多信息,请告诉我。

我在这里复制了我稍作改动的代码(删除了一些日志记录,添加了一些注释)。 LsZFutelszHavi 是 A 类实体Class,LsZFutelsz 是 B 类实体Class.

Konverter 摘要 class。它为每个 DBASE table

继承
public abstract class Konverter<RepositoryType extends     CrudRepository<EntityType,Integer>, EntityType> {
protected String dbfPath;
protected DBaseTable sourceTable = null;
protected Logger logger;
protected RepositoryType repository;
protected String dBaseEncoding = DBaseTable.CP852;

public Konverter(String dbfPath, Logger logger, RepositoryType repository) {
    this.dbfPath = dbfPath;
    this.logger = logger;
    this.repository = repository;
}

/*
This method should be called, to start converting
*/
@Transactional
public void konvert() {
    try {
        /*It loads the DBASE database*/     
        File sourceFile = new File(fileName);
        sourceTable = new DBaseTable(sourceFile, dBaseEncoding);
        sourceTable.open(IfNonExistent.ERROR);

        Iterator<Record> recordIterator = sourceTable.recordIterator();            
        int count = 0;
        try {
            /*Converts the database table row by row*/
            count = konvertSorok(recordIterator);
        } catch (Exception e) {
            throw e;
        } finally {
            sourceTable.close();
        }
    }
    catch (CorruptedTableException | IOException | RuntimeException e) {
        logger.error(QsLoggerUtils.getStackTraceString(e));//e.printStackTrace();
    }

}

private int konvertSorok(Iterator<Record> recordIterator) {
    int count = 0;
    /*Converts the database table row by row*/
    while(recordIterator.hasNext())
    {
        Record record = recordIterator.next();
        /* Converting one row */
        List<EntityType> entityIterable = konvertToEntity( record );

        for (EntityType entityType : entityIterable) {
            repository.save(entityType);                
        }
        count++;
    }       
    return count;
}

/**
 * This should be implemented in the child method
 * @param record
 * @return
 */
protected abstract List<EntityType> konvertToEntity(Record record); 
}

child Class,实现了 konvertToEntity 方法。

public class Konvert14FutelszHavi extends Konverter<LsZFutelszHaviRepository,LsZFutelszHavi> {

private static Logger logger = LoggerFactory.getLogger(Konvert12Futalany.class);

LsZFutelszHaviRepository lsZFutelszHaviRepository;
LsTLakoRepository lsTLakoRepository; 
LsZFutelszRepository lsZFutelszRepository;
LsTEvhoRepository lsTEvhoRepository;


@Autowired
public Konvert14FutelszHavi(LsZFutelszHaviRepository lsZFutelszHaviRepository,
                            LsTLakoRepository lsTLakoRepository,
                            LsZFutelszRepository lsZFutelszRepository,
                            LsTEvhoRepository lsTEvhoRepository) throws IOException {
    super(DBaseTable.chkFile(AppKonvertLax.PATH_LSZBF, AppKonvertLax.SOURCE_FILE_FUTELSZ_HAVI), logger, lsZFutelszHaviRepository);
    dBaseEncoding = DBaseTable.CP1250;
    this.lsTLakoRepository = lsTLakoRepository;
    this.lsZFutelszHaviRepository = lsZFutelszHaviRepository;
    this.lsZFutelszRepository = lsZFutelszRepository;
    this.lsTEvhoRepository = lsTEvhoRepository;
}

@Override
protected List<LsZFutelszHavi> konvertToEntity(Record record) {
    String ukod     = record.getStringValue("UKOD").substring(1).trim();        
    BigDecimal ekaptam  = new BigDecimal(record.getNumberValue("EKAPTAM").toString());        
    BigDecimal efutkul  = new BigDecimal(record.getNumberValue("EFUTKUL").toString());              

    ArrayList<LsZFutelszHavi> returnArray = new ArrayList<LsZFutelszHavi>();
    LsTLako lsTLako = lsTLakoRepository.findOneByLakoKod(ukod);
    LsZFutelsz lsZFutelsz = lsZFutelszRepository.findOneByLsTLako(lsTLako);
    if (lsZFutelsz == null) {
        return returnArray;
    }
    /* Here is the modification in the lsZFutelsz (Type B) entity */
    lsZFutelsz.setSzezVegenBefOssz(ekaptam);

    /* From 10th month to 4th */
    for (int i=10; i!=5; i++) {
        if (i==13) { 
            i = 1;
        }
        String keyNumber = Integer.toString(i);
        if (keyNumber.length() == 1) {
            keyNumber = "0" + keyNumber;
        }
        BigDecimal fk = new BigDecimal(record.getNumberValue("FK_"+keyNumber).toString());
        LsZFutelszHavi lsZFutelszHavi = new LsZFutelszHavi();
        LsTEvho lsTEvho = lsTEvhoRepository.findOneByEvAndHo(2014, i);
        lsZFutelszHavi.setLsTEvho(lsTEvho);
        lsZFutelszHavi.setFizKorrOssz(fk);
        lsZFutelszHavi.setOrigKorrOssz(efutkul);
        /* This should be enough to save the lsZFutelsz entity modification I would think */
        lsZFutelszHavi.setLsZFutelsz(lsZFutelsz);
        returnArray.add(lsZFutelszHavi);
    }

    /* Even this does not help */
    lsZFutelszRepository.save(lsZFutelsz);

    return returnArray;
}

}

B 类实体的存储库

@RepositoryRestResource(collectionResourceRel = LsZFutelszHavi.VERB_FUTELSZ, path = LsZFutelszHavi.VERB_FUTELSZ)
public interface LsZFutelszRepository extends PagingAndSortingRepository<LsZFutelsz, Integer> {
    /*-----------------------------------------------------------------------------------------------*/
    @RestResource(exported=false)
    @Modifying
    @Query(value="DELETE FROM ls_z_futelsz f WHERE f.lako_id = ?1", nativeQuery=true)
    void deleteByLako(Integer integer);
    /*-----------------------------------------------------------------------------------------------*/ 
    LsZFutelsz findOneByLsTLako(LsTLako lsTLako);
}

A 类实体的存储库

@RepositoryRestResource(collectionResourceRel = LsZFutelsz.VERB_FUTELSZHAVI, path = LsZFutelsz.VERB_FUTELSZHAVI)
public interface LsZFutelszHaviRepository extends PagingAndSortingRepository<LsZFutelszHavi, Integer> {

}

实体类型 A

@Entity
@Table(name="LS_Z_FUTELSZ_HAVI")
@NamedQuery(name="LsZFutelszHavi.findAll", query="SELECT l FROM LsZFutelszHavi l")
public class LsZFutelszHavi extends Audit implements Serializable {

    public static final String VERB_FUTELSZ  = "futelszamolasok";
    /*-----------------------------------------------------------------------------------------------*/
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="GenFutelszHaviID", sequenceName="GEN_LS_Z_FUTELSZ_HAVI_ID", allocationSize= 1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="GenFutelszHaviID")
    @Column(name="HAVI_ELSZ_ID")
    private Integer haviElszId;

    @NotNull
    @Column(name="FIZ_KORR_OSSZ")
    private BigDecimal fizKorrOssz;

    @NotNull
    @Column(name="ORIG_KORR_OSSZ")
    private BigDecimal origKorrOssz;

    //uni-directional many-to-one association to LsFSzlafej
    @ManyToOne
    @JoinColumn(name="SZLA_ID")
    private LsFSzlafej lsFSzlafej;

    //uni-directional many-to-one association to LsTEvho
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="EV", referencedColumnName="EV"),
        @JoinColumn(name="HO", referencedColumnName="HO")
        })
    private LsTEvho lsTEvho;

    //bi-directional many-to-one association to LsZFutelsz
    @ManyToOne
    @JoinColumn(name="ELSZ_ID")
    private LsZFutelsz lsZFutelsz;

    public LsZFutelszHavi() {
    }
    //[... setters getters ...]
}

实体类型 B

@Entity
@Table(name="LS_Z_FUTELSZ")
@NamedQuery(name="LsZFutelsz.findAll", query="SELECT l FROM LsZFutelsz l")
public class LsZFutelsz extends Audit implements Serializable {
    public static final String VERB_FUTELSZHAVI = "futelszhavi";
    /*-----------------------------------------------------------------------------------------------*/
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="GenFutelszID", sequenceName="GEN_LS_Z_FUTELSZ_ID", allocationSize= 1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="GenFutelszID")
    @Column(name="ELSZ_ID")
    private Integer elszId;

    @NotNull
    @Column(name="LEOLV_FOGY_GJ")
    private BigDecimal leolvFogyGj = BigDecimal.ZERO;

    @NotNull
    @Column(name="LEOLV_FOGY_OSSZ")
    private BigDecimal leolvFogyOssz = BigDecimal.ZERO;

    @NotNull
    @Column(name="ELOZ_SZEZ_OSSZ")
    private BigDecimal elozSzezOssz = BigDecimal.ZERO;

    @NotNull
    @Column(name="SZEZ_VEGEN_BEF_OSSZ")
    private BigDecimal szezVegenBefOssz = BigDecimal.ZERO;

    @NotNull
    @Column(name="SZOSZT_UTAN_FENNM")
    private BigDecimal szosztUtanFennm = BigDecimal.ZERO;

    @NotNull
    @Column(name="SZOSZTANDO_KULONB")
    private BigDecimal szosztandoKulonb = BigDecimal.ZERO;

    //uni-directional many-to-one association to LsTLakok
    @ManyToOne
    @JoinColumn(name="LAKO_ID")
    private LsTLako lsTLako;

    //bi-directional many-to-one association to LsZFutelszHavi
    @OneToMany(mappedBy="lsZFutelsz", cascade={CascadeType.REMOVE})
    private List<LsZFutelszHavi> lsZFutelszHaviTetelek;

    public LsZFutelsz() {
    }
    //[... setters getters ...]
}

代码有效,该字段总是恰好是默认值。

用简单的方法测试后,另一个实体也被保存到数据库中。然后我在原始代码中放置一个断点,如果实体的新值与默认值不同,它只会被破坏。该程序转换了所有内容而没有在断点处中断。

所以,我查看了我正在转换的数据库,看看内容是什么。令我惊讶的是,它始终为零,即默认值。

这很尴尬。我很确定,我误解了一些东西,并且编码错误。