MyBatis 3中实现一对多的插入和查询

summary:

MyBatis3中实现一对多的查询比较简单,可以自动完成。但插入操作要复杂一些,需要相关的DAO配合完成,这点不如Hibernate。


场景描述:

类:Mail和Attachment类

关系描述:一封邮件(Mail)可以有0个或多个附件(Attachment),附件(Attachment)仅对应一封邮件。

表格:mail表(主键:id_mail)和attachment表(外键:id_mail)。


POJO:

Mail.java
public class Mail implements Serializable {
	private static final long serialVersionUID = 7427977743354005783L;
	private Integer id;
	private String sender;
	private String subject;
	private String content;
	private String fromAddress;
...
getters and setters...
}
Attachment.java
public class Attachment implements Serializable {
	private static final long serialVersionUID = -1863183546552222728L;
	private String id;
	private String mailId;
	private String name;
	private String relativePath;
...
getters and setters...
}

SqlMapConfig:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties resource="test/properties/mysql.properties"></properties>
	
	<typeAliases>
		<typeAlias type="test.model.Mail" alias="Mail"/>
		<typeAlias type="test.model.Attachment" alias="Attachment"/>		
	</typeAliases>
	
	
    <environments default="development">
    	<environment id="development">
        	<transactionManager type="JDBC" />
            <dataSource type="UNPOOLED">
            	<property name="driver" value="${db_driver}" />
                <property name="url" value="${db_url}" />
                <property name="username" value="${db_user}" />
                <property name="password" value="${db_password}"/>
            </dataSource>
        </environment>
    </environments>  
    	
    <mappers>
	<mapper resource="test/data/MailMapper.xml"/>
	<mapper resource="test/data/AttachmentMapper.xml"/>
    </mappers>	
</configuration>

Mappers

MailMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test.data.MailMapper">
	<cache />

	<resultMap type="Mail" id="result_base">
		<id property="id" column="id_mail" />
		<result property="sender" column="sender"/>
		<result property="fromAddress" column="from_address" />
		<result property="subject" column="subject"/>
		<result property="content" column="content"/>
		<result property="sendTime" column="send_time" />
	        ....
	</resultMap>
	<!--这里是关键,一对多映射的“魔法”几乎都在<collection>的配置里。select=...中"test.data.AttachmentMapper"对应于AttachmentMapper中
            的namespace-->
	<resultMap type="Mail" id="result" extends="result_base">
		<collection property="attachments" javaType="ArrayList" column="id_mail" ofType="Attachment" 
		select="test.data.AttachmentMapper.selectByMailId"/>
	</resultMap>
	
	<insert id="insert" parameterType="Mail" useGeneratedKeys="true" keyProperty="id_note">
		insert into note(sender, from_address, subject, content, send_time)
		values(#{sender}, #{fromAddress}, #{subject}, #{content}, #{sendTime})
		<selectKey keyProperty="id_mail" resultType="int"> 
                      select LAST_INSERT_ID() 
                </selectKey> 
	</insert>
	
	<select id="selectById" parameterType="int" resultMap="result" >
		select * from mail where id_mail = #{id}
	</select>
	
	<select id="selectAllMails" resultMap="result">
		select * from note Note
	</select>
	<!--这里可以获得刚插入表格的id,为后面attachment的插入提供了mailId字段-->
	<select id="selectLastId" resultType="int">
		 select LAST_INSERT_ID() 
	</select>
</mapper>
AttachmentMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test.data.AttachmentMapper">
	<cache />
	
	<resultMap type="Attachment" id="result">
		<result property="id" column="id_accessory" />
		<result property="name" column="name" />
		<result property="relativePath" column="relative_path" />
		<result property="mailId" column="id_mail" />
	</resultMap>
	
	<insert id="insert" parameterType="Attachment">
		insert into attachments(id_mail, name, relative_path) values(#{mailId}, #{name}, #{relativePath})
	</insert>
	<!--MailMapper中的ResultMap调用这个方法来进行关联-->
	<select id="selectByMailId" parameterType="int" resultMap="result">
		select 	id, id_mail, name, relative_path
		 from attachments where id_note = #{id}
	</select>
</mapper>

DAO

AttachmentDAO
public class AttachmentDAO {
	private SqlSessionFactory sqlSessionFactory;
	
	public AttachmentDAO(){
		this.sqlSessionFactory = TestConnectionFactory.getSqlSessionFactory();
	}
	
	public void insert(Attachment attachment){
             SqlSession session = sqlSessionFactory.openSession();
    	     AttachmentMapper attachmentMapper = session.getMapper(AttachmentMapper.class); 
             try {
                attachmentMapper.insert(attachment);
                session.commit();
             } finally {
                session.close();
             }
	}
}

MailDAO
public class MailDAO {
    private SqlSessionFactory sqlSessionFactory;
	 
    public MailDAO(){
        sqlSessionFactory = TestConnectionFactory.getSqlSessionFactory();
    } 
    
    public void insertMailOnly(Mail mail){
    	SqlSession session = sqlSessionFactory.openSession();
    	MailMapper mailMapper = session.getMapper(MailMapper.class);
        try {
            mailMapper.insert(mail);       
            session.commit();
        } finally {
            session.close();
        }
    } 
    //inset 
    public void insertMail(Mail mail){
    	SqlSession session = sqlSessionFactory.openSession();
    	MailMapper mailMapper = session.getMapper(MailMapper.class);
    	AttachmentMapper attachmentMapper = session.getMapper(AttachmentMapper.class);
    	
    	try{
	    	mailMapper.insert(mail);
	    	//这里必须commit,再执行Attachment的插入操作。否则会导致null pointer异常
	    	session.commit();
	    	//获得最近插入到note表的id
	    	int mailId = mailMapper.selectLastId();
	    	for(Attachment attach : mail.getAttachments()){
	    		attach.setMailId(String.valueOf(mailId));
	    		attachmentMapper.insert(attach);
	    	}
	    	session.commit();
    	}finally{
    		session.close();
    	}
    }
    
    public ArrayList<Mail> selectAllMails(){    	
    	ArrayList<Mail> mailList = null;
    	SqlSession session = sqlSessionFactory.openSession();
    	MailMapper mailMapper = session.getMapper(MailMapper.class);
        try {        	
            mailList = mailMapper.selectAllMails();
            session.commit();
        } finally {
            session.close();
        }
	return mailList;
    } 
    
    public Mail selectMailById(int i){
    	Mail mail = null;
    	SqlSession session = sqlSessionFactory.openSession();
    	MailMapper mailMapper = session.getMapper(MailMapper.class);
        try {        	
        	mail = mailMapper.selectById(i);
            session.commit();
        } finally {
            session.close();
        }
	return mail;
    }
    
    public int selectLastId(){
    	int id = -1;
    	SqlSession session = sqlSessionFactory.openSession();
    	MailMapper mailMapper = session.getMapper(MailMapper.class);
        try {        	
            id = mailMapper.selectLastId();
            session.commit();
        } finally {
            session.close();
        }
	return id;
    }
}



MyBatis是一个开源的持久层框架,它可以帮助我们简化数据库操作的编写。在MyBatis一对多插入是指在一个实体对象包含多个关联对象,并将它们一起插入到数据库实现一对多插入的步骤如下: 1. 首先,需要定义好实体类和关联对象的映射关系。在实体类,使用集合类型来表示关联对象的集合。 2. 在MyBatis的映射文件,使用<collection>标签来定义关联对象的集合属性,并指定关联对象的映射关系。 3. 在插入操作时,先插入主对象,获取主对象的主键值。 4. 遍历关联对象集合,设置每个关联对象的外键属性为主对象的主键值,并插入到数据库。 下面是一个示例代码,演示了如何使用MyBatis实现一对多插入: ```java // 实体类 public class Order { private int id; private String orderNo; private List<OrderItem> orderItems; // 省略getter和setter方法 } public class OrderItem { private int id; private String itemName; private int orderId; // 省略getter和setter方法 } // 映射文件 <!-- OrderMapper.xml --> <mapper namespace="com.example.mapper.OrderMapper"> <resultMap id="orderResultMap" type="Order"> <id property="id" column="id"/> <result property="orderNo" column="order_no"/> <collection property="orderItems" ofType="OrderItem"> <id property="id" column="item_id"/> <result property="itemName" column="item_name"/> <result property="orderId" column="order_id"/> </collection> </resultMap> <insert id="insertOrder" parameterType="Order"> <!-- 插入主对象 --> INSERT INTO orders (order_no) VALUES (#{orderNo}) </insert> <insert id="insertOrderItems" parameterType="Order"> <!-- 插入关联对象 --> <foreach collection="orderItems" item="item"> INSERT INTO order_items (item_name, order_id) VALUES (#{item.itemName}, #{item.orderId}) </foreach> </insert> </mapper> // DAO接口 public interface OrderMapper { void insertOrder(Order order); void insertOrderItems(Order order); } // 使用示例 public class Main { public static void main(String[] args) { SqlSessionFactory sqlSessionFactory = ...; // 初始化SqlSessionFactory try (SqlSession sqlSession = sqlSessionFactory.openSession()) { OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class); Order order = new Order(); order.setOrderNo("20210001"); List<OrderItem> orderItems = new ArrayList<>(); OrderItem item1 = new OrderItem(); item1.setItemName("Item 1"); orderItems.add(item1); OrderItem item2 = new OrderItem(); item2.setItemName("Item 2"); orderItems.add(item2); order.setOrderItems(orderItems); orderMapper.insertOrder(order); // 插入主对象 orderMapper.insertOrderItems(order); // 插入关联对象 sqlSession.commit(); } } } ```
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值