1

我的问题是保留两个具有 1:n 关系的类:

public class DayRecord {
    private Long id;
    private List<TimeRecord> timeRecordsToday = new ArrayList<TimeRecord>(4);
    ...
}

public class TimeRecord {
    private Long id;
    ...
}

因此,在代码中,DayRecord 知道 TimeRecord。

create table DAY_RECORDS (
    id int primary key,
);

create table TIME_RECORDS (
    id int primary key,
    day_record_id int not null,
    foreign key (day_record_id) references DAY_RECORDS (id)
);

在数据库中,TimeRecord 知道 DayRecord。

我可以一步保存包含所有 TimeRecord 的 DayRecord 吗?

在 Hibernate 中,我可以设置一个逆映射并只保存一个 DayRecord,它的所有 TimeRecords 也会被保存。使用 MyBatis,我尝试将这些类彼此独立地保存:

<mapper
    namespace="de.stevenschwenke.java.javafx.xyz.DayRecordMapper">
    <insert id="insertDayRecord" 
        parameterType="de.stevenschwenke.java.javafx.xyz.DayRecord">
        insert into DAY_RECORDS (id) values (NEXT VALUE FOR DAY_RECORDS_SEQ);
    </insert>
</mapper>

<mapper
    namespace="de.stevenschwenke.java.javafx.xyz.TimeRecordMapper">
    <insert id="insertTimeRecord"
        parameterType="de.stevenschwenke.java.javafx.xyz.TimeRecord">
        insert into TIME_RECORDS (id) values (NEXT VALUE FOR TIME_RECORDS_SEQ);
    </insert>
</mapper>

但是如何将 DayRecord-ID 保存在 TimeRecord 中?

想法:

  1. 给 TimeRecord 一个属性 dayRecordId。这样,将创建一个循环依赖项。但是,映射会在保存时处理相关性。
  2. 在一个事务中,首先保存 DayRecord,获取其 ID,将其设置在 TimeRecords 中并保存此对象。
  3. 在插入中使用嵌套的选择语句,就像在文档中一样

保存这两个对象的最佳方法是什么?谢谢你的帮助!

4

2 回答 2

2

正如 jdevelop 已经提到的,MyBatis 只是一个 SQL 包装器。因为 SQL 没有提供插入两个有关系的对象的方法,所以 MyBatis 也不能这样做。

所以这是我的解决方法:正如我所提到的,我不想通过让 TimeRecord 知道 DayRecord 来添加循环依赖。所以我创建了一个包装类,只用于插入 TimeRecords:

public class TimeRecordInsertWrapper {
    public Long id;
    public int hours;
    public long dayRecordId;
    [constructor/getter/setter omited but there with public access modifier]
}

首先,我存储 DayRecord 并获取它的 ID。然后我创建包装对象并存储 TimeRecords:

public long insertDayRecord(DayRecord newRecord) {
    SqlSession session = sqlSessionFactory.openSession();
    try {

        session.insert(
                "de.stevenschwenke.java.javafx.xyz.DayRecordMapper.insertDayRecord",
                newRecord);

        for (TimeRecord tr : newRecord.getTimeRecordsToday()) {
            TimeRecordInsertWrapper wrapper = new TimeRecordInsertWrapper(tr.getHours(), newRecord.getId());
            session.insert("de.stevenschwenke.java.javafx.xyz.TimeRecordMapper.insertTimeRecord",
                    wrapper);
        }
        return newRecord.getId();
    } finally {
        session.commit();
        session.close();
    }
}

这样,我可以使用我漂亮的单向对象模型并在数据库中拥有“正确”的映射。

于 2013-06-09T09:33:33.697 回答
1

Mybatis 只是一个 SQL 映射框架,它允许你从 Java 代码中抽象出 SQL 代码,差不多就是这样。他们假装看起来像最新版本的 Hibernate,但这会导致 XML 中的奇怪结构。

我建议存储 DayRecord 并从 selectKey 获取它,然后在随后调用映射器时使用该 ID。这是映射器内部实际发生的情况,但复杂的 XML 意味着要在内部构建复杂的 FSM。所以保持简单,你可以安全地使用 myBatis,或者使用 Hibernate。

更好的是,您可以为任务定义自定义 DAO 接口,然后您可以拥有某种带有 @Transactional 属性集的服务层。这需要mybatis-guice,但它的效果非常好,而且您不需要处理代码中的事务(它们是声明性的)。

于 2013-06-07T19:05:53.277 回答