MyBatis:如何绘制地图;逆;关系

MyBatis:如何绘制地图;逆;关系,mybatis,Mybatis,我的问题是保持两个具有1:n关系的类: public class DayRecord { private Long id; private List<TimeRecord> timeRecordsToday = new ArrayList<TimeRecord>(4); ... } public class TimeRecord { private Long id; ... } 在数据库中,TimeRecord知道DayReco

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

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

public class TimeRecord {
    private Long id;
    ...
}
在数据库中,TimeRecord知道DayRecord

我可以一步保存一个DayRecord及其所有时间记录吗?

在Hibernate中,我可以设置一个反向映射,只保存一个DayRecord,它的所有时间记录也会被保存。在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>

插入日记录(id)值(日记录的下一个值);
插入时间记录(id)值(时间记录的下一个值);
但是我如何保存DayRecord ID inTimeRecord

想法:

  • 为TimeRecord指定一个属性dayRecordId。这样,将创建一个循环依赖项。但是,映射将在保存时考虑数据的好处
  • 在一个事务中,首先保存DayRecord,获取其ID,在TimeRecords中设置它并保存此对象
  • 在insert中使用嵌套的select语句,如文档中所示

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

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

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


    更棒的是,您可以为任务定义自定义DAO接口,然后可以使用@Transactional属性集创建某种服务层。这需要,但它工作得非常好,您不需要在代码中处理事务(它们是声明性的)。

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

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

    public class TimeRecordInsertWrapper {
        public Long id;
        public int hours;
        public long dayRecordId;
        [constructor/getter/setter omited but there with public access modifier]
    }
    
    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();
        }
    }
    
    首先,我存储DayRecord并获取它的ID。然后我创建包装器对象并存储TimeRecords:

    public class TimeRecordInsertWrapper {
        public Long id;
        public int hours;
        public long dayRecordId;
        [constructor/getter/setter omited but there with public access modifier]
    }
    
    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();
        }
    }
    

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

    感谢您的快速回答!首先保存DayRecord是我的想法。但是,在这样做时,我必须将dayRecordId添加到TimeRecord,对吗?这就是我想要避免的。导航只能从DayRecord转到TimeRecord。