简体   繁体   English

关联实体未保存在事务中

[英]Associated Entity does not get saved in transaction

I am fairly new to entity frameworks, and don't understand why my entity does not get saved correctly. 我对实体框架还很陌生,并且不明白为什么我的实体无法正确保存。

edit: 编辑:

I will try to out this test code soon, and see if it works: 我将尽快尝试删除此测试代码,并查看其是否有效:

@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);
}

I am trying to convert from an old DBASE database, to a Firebird database. 我正在尝试从旧的DBASE数据库转换为Firebird数据库。 The Firebird database have it's tables mapped by entities. Firebird数据库具有按实体映射的表。 I read a DBASE table, then convert it row by row. 我读取了一个DBASE表,然后将其逐行转换。

I use @Transactional, to either save all converted entities of the DBASE table, or save none. 我使用@Transactional来保存DBASE表的所有已转换实体,或者不保存任何实体。

I managed to convert every table correctly into the new database except one. 我设法将每个表正确地转换到除了一个表之外的新数据库。

In the other tables, I only had to save one entity per record, and did not have to modify other type of entities. 在其他表中,我只需要为每条记录保存一个实体,而不必修改其他类型的实体。 I usually had to create a Type X entity, connect it to a Type Y entity, then save. 我通常必须创建一个X型实体,将其连接到Y型实体,然后保存。 For save, I use a repository for the entity (an org.springframework.data.repository.PagingAndSortingRepository if it matters) 为了保存,我使用实体的存储库(如果重要的话,使用org.springframework.data.repository.PagingAndSortingRepository)

In that particular DBASE table, I have to create one entity of Type A, connect it to a Type B entity, modify the Type B entity, then save. 在那个特定的DBASE表中,我必须创建一个Type A实体,将其连接到Type B实体,修改Type B实体,然后保存。 The problem is, that Type B entity modification does not get saved into the Firebird table. 问题在于,Type B实体修改未保存到Firebird表中。 Again, I use a repository to save the entity. 同样,我使用存储库来保存实体。

To get the Type B entity, I use it's repository's method: 要获取B型实体,我使用它的存储库方法:

LsZFutelsz findOneByLsTLako(LsTLako lsTLako); 

I guessed, that maybe if I save this Type B entity with it's own repository, it would get modified in the database correctly. 我猜想,也许如果我将B型实体与它自己的存储库一起保存,它将在数据库中正确修改。 It did not help. 它没有帮助。

Please tell me if additional information is needed. 请告诉我是否需要其他信息。

I copy my slightly altered code here (removed some logging, added some comments). 我在这里复制了稍作改动的代码(删除了一些日志记录,添加了一些注释)。 LsZFutelszHavi is the Type A EntityClass, LsZFutelsz is type B EntityClass. LsZFutelszHavi是类型A EntityClass,LsZFutelsz是B类型EntityClass。

The Konverter abstract class. Konverter抽象类。 It is inherited for every DBASE table 它为每个DBASE表继承

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); 
}

The child Class, that implmenets konvertToEntity method. 子类,表示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;
}

}

Repository for the Type B entity 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);
}

Repository for the Type A entity A型实体的存储库

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

}

Entity Type A 实体类型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 ...]
}

Entity Type B 实体类型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 ...]
}

The code works, The field is just always happen to be the default value. 该代码工作正常,该字段总是总是碰巧是默认值。

After testing it with simple methods, the other entity got saved into the database as well. 用简单的方法测试它之后,另一个实体也被保存到数据库中。 Then I put a breakpoint into the original code which only get breaked, if the new value for the entity is different than the default. 然后,如果实体的新值与默认值不同,则会在原始代码中放置一个断点,该断点只会中断。 The program converted everything without breaking at the breakpoint. 该程序在不中断的情况下转换了所有内容。

So, I looked up which database I converting, and see what the contents ar. 因此,我查找了要转换的数据库,并查看了其中的内容。 To my surprise it was always zero, the default value. 令我惊讶的是,它始终是零,即默认值。

It's awkward. 好尴尬 I was so sure, I misunderstood something, and coded wrong. 我非常确定,我误会了一些东西,并且编码错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM