MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
一对一映射
在生活中,一对一的例子还是有的,比如啦,学生和身份证哦,或者在我国,实行的是一夫一妻制度哦。那么我们以学生和身份证每个学生只有一张身份证,而每张身份证的主人当然只有一个啦。
数据库脚本:
-- 删除数据库 drop database if exists mybaits; -- 创建数据库 create database if not exists mybatis default character set utf8; -- 选择数据库 use mybatis; -- 删除数据表 drop table if exists student ; drop table if exists card; -- 创建数据表 create table card( cid int(255), num varchar(18), constraint pk_cid primary key (cid) ); create table student( sid int(255), sname varchar(32), scid int(255), constraint pk_sid primary key (sid), constraint fk_scid foreign key (scid) references card(cid) ); -- 增加测试数据 insert into card (cid,num) values(1,'123456789012345678'); insert into student (sid,sname,scid) values(1,'哈哈',1);
新建一个one2one.Card.java类
package one2one; import java.io.Serializable; /** * 身份证 * @author Administrator * */ @SuppressWarnings("serial") public class Card implements Serializable{ private Integer cid; private String num; public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getNum() { return num; } public void setNum(String num) { this.num = num; } }
新建one2one.Student.java类
package one2one; import java.io.Serializable; /** * 学生 * @author Administrator * */ @SuppressWarnings("serial") public class Student implements Serializable{ private Integer sid; private String sname; private Card card; public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Card getCard() { return card; } public void setCard(Card card) { this.card = card; } }
在one2one包下新建CardMapper.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="cardNameSpace"> <resultMap type="one2one.Card" id="cardMap"> <id column="cid" property="cid"/> <result column="num" property="num"/> </resultMap> </mapper>
同理,在one2one包下新建StudentMapper.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="studentNameSpace"> <resultMap type="one2one.Student" id="studentMap"> <id column="sid" property="sid"/> <result column="sname" property="sname"/> <!-- 关联字段不要写 --> </resultMap> <select id="findById" parameterType="integer" resultMap="studentMap"> select s.sid,s.sname,c.cid,c.num from student s,card c where s.scid = c.cid and s.sid = #{sid} </select> </mapper>
在src下新建一个mybatis.cfg.xml文件,并包含StudentMapper.xml和CardMapper.xml文件
<?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> <!-- 设置一个默认的环境信息 --> <environments default="mysql_developer"> <!-- 连接MySQL环境信息 --> <environment id="mysql_developer"> <!-- MyBatis使用jdbc事务管理器 --> <transactionManager type="jdbc"/> <!-- MyBatis使用连接池方式来获取连接对象 --> <dataSource type="pooled"> <!-- 配置与数据库交互的4个必要属性 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="mysqladmin"/> </dataSource> </environment> <!-- 连接Oracle环境信息 --> <environment id="oracle_developer"> <!-- MyBatis使用jdbc事务管理器 --> <transactionManager type="jdbc"/> <!-- MyBatis使用连接池方式来获取连接对象 --> <dataSource type="pooled"> <!-- 配置与数据库交互的4个必要属性 --> <property name="driver" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/> <property name="username" value="scott"/> <property name="password" value="tiger"/> </dataSource> </environment> </environments> <!-- 加载映射文件 --> <mappers> <mapper resource="one2one/CardMapper.xml"/> <mapper resource="one2one/StudentMapper.xml"/> </mappers> </configuration>
在util包下新建一个工具类MyBatisUtil.java类
package util; import java.io.IOException; import java.io.Reader; import java.sql.Connection; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisUtil { private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>(); public static SqlSessionFactory sqlSessionFactory ; //私有化构造方法 private MyBatisUtil(){} //加载位于src/Mybatis.cfg.xml static{ try { Reader reader = Resources.getResourceAsReader("mybatis.cfg.xml"); sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } /** * 获取SQLSession * @return */ public static SqlSession getSqlSession(){ //从当前线程中获取SqlSession对象 SqlSession sqlSession = threadLocal.get(); if(sqlSession == null){ if(sqlSessionFactory != null){ sqlSession = sqlSessionFactory.openSession(); //讲sqlSession与当前线程绑定在一起 threadLocal.set(sqlSession); } } return sqlSession; } /** * 关闭SqlSession 并与当前线程分开 */ public static void closeSqlSession(){ //从当前线程中获取SqlSession对象 SqlSession sqlSession = threadLocal.get(); //如果SqlSession对象非空 if(sqlSession != null){ //关闭SqlSession对象 sqlSession.close(); //分离当前线程与SqlSession的关系 threadLocal.remove(); } } //测试 public static void main(String[] args) { SqlSession sqlSession = MyBatisUtil.getSqlSession(); Connection conn= sqlSession.getConnection(); System.out.println(conn != null ?"连接成功":"连接失败"); } }
新建持久层类StuentCardDAO.java类
package one2one; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import util.MyBatisUtil; /** * 持久层 * @author Administrator * */ public class StudentCardDAO { /** * 查询1号学生的信息与身份证信息 * @param id * @return * @throws Exception */ public Student findById(Integer id) throws Exception{ SqlSession sqlSession = null; try { sqlSession = MyBatisUtil.getSqlSession(); return sqlSession.selectOne("studentNameSpace.findById", id); } catch (Exception e) { e.printStackTrace(); throw e; }finally{ MyBatisUtil.closeSqlSession(); } } //测试 查询1号学生的信息与身份证信息 @Test public void testFindById() throws Exception{ StudentCardDAO dao = new StudentCardDAO(); Student student = dao.findById(1); System.out.println(student.getSid()+":"+student.getSname() } }
这时我们只能查询1号学生的姓名,但是我们不能去查询它的身份号号,因为此时的card属性的值为null,从StudentMapper.xml中可以看出
<select id="findById" parameterType="integer" resultMap="studentMap">
MyBatis在解析这一句的时候只能将查询的数据封装到sid,sname中,所以怎么办?
在StudentMapper.xml中的
<resultMap type="one2one.Card" id="cardMap"> <id column="cid" property="cid"/> <result column="num" property="num"/> </resultMap>
增加
<!-- 引入CardMapper.xml文件中的映射信息 property表示Student的关联属性 --> <association property="card" resultMap="cardNameSpace.cardMap"/>
那么此时的StudentMapper.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="studentNameSpace"> <resultMap type="one2one.Student" id="studentMap"> <id column="sid" property="sid"/> <result column="sname" property="sname"/> <!-- 引入CardMapper.xml文件中的映射信息 property表示Student的关联属性 --> <association property="card" resultMap="cardNameSpace.cardMap"/> </resultMap> <select id="findById" parameterType="integer" resultMap="studentMap"> select s.sid,s.sname,c.cid,c.num from student s,card c where s.scid = c.cid and s.sid = #{sid} </select> </mapper>
现在可以测试学生的身份证号码了
将持久层类StuentCardDAO.java类的测试方法改为
//测试 查询1号学生的信息与身份证信息 @Test public void testFindById() throws Exception{ StudentCardDAO dao = new StudentCardDAO(); Student student = dao.findById(1); System.out.println(student.getSid()+":"+student.getSname()+":"+student.getCard().getNum()); }
同理
在StudentDAO.java类中增加 查询“哈哈”学生的信息与身份证信息的方法
/** * 查询“哈哈”学生的信息与身份证信息 * @param name * @return * @throws Exception */ public Student findByName(String name) throws Exception{ SqlSession sqlSession = null; try { sqlSession = MyBatisUtil.getSqlSession(); return sqlSession.selectOne("studentNameSpace.findByName", name); } catch (Exception e) { e.printStackTrace(); throw e; }finally{ MyBatisUtil.closeSqlSession(); } }
并增加测试方法哦
//测试 查询“哈哈”学生的信息与身份证信息 @Test public void testFindByName() throws Exception{ StudentCardDAO dao = new StudentCardDAO(); Student student = dao.findByName("哈哈"); System.out.println(student.getSid()+":"+student.getSname()+":"+student.getCard().getNum()); }
当然如果你现在就测试,你会死的很惨,因为你没有在StudentMapper.xml文件中配置<select>哦,所以在StudentMapper.xml文件中增加<select>配置信息
<select id="findByName" parameterType="string" resultMap="studentMap"> select s.sid,s.sname,c.cid,c.num from student s,card c where s.scid = c.cid and s.sname = #{sname} </select>
这样就可以测试成功了。大功告成。
完整代码如下:
MySQL数据库脚本
-- 删除数据库 drop database if exists mybaits; -- 创建数据库 create database if not exists mybatis default character set utf8; -- 选择数据库 use mybatis; -- 删除数据表 drop table if exists student ; drop table if exists card; -- 创建数据表 create table card( cid int(255), num varchar(18), constraint pk_cid primary key (cid) ); create table student( sid int(255), sname varchar(32), scid int(255), constraint pk_sid primary key (sid), constraint fk_scid foreign key (scid) references card(cid) ); -- 增加测试数据 insert into card (cid,num) values(1,'123456789012345678'); insert into student (sid,sname,scid) values(1,'哈哈',1);
工具类MyBatis.java类
package util; import java.io.IOException; import java.io.Reader; import java.sql.Connection; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisUtil { private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>(); public static SqlSessionFactory sqlSessionFactory ; //私有化构造方法 private MyBatisUtil(){} //加载位于src/Mybatis.cfg.xml static{ try { Reader reader = Resources.getResourceAsReader("mybatis.cfg.xml"); sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } /** * 获取SQLSession * @return */ public static SqlSession getSqlSession(){ //从当前线程中获取SqlSession对象 SqlSession sqlSession = threadLocal.get(); if(sqlSession == null){ if(sqlSessionFactory != null){ sqlSession = sqlSessionFactory.openSession(); //讲sqlSession与当前线程绑定在一起 threadLocal.set(sqlSession); } } return sqlSession; } /** * 关闭SqlSession 并与当前线程分开 */ public static void closeSqlSession(){ //从当前线程中获取SqlSession对象 SqlSession sqlSession = threadLocal.get(); //如果SqlSession对象非空 if(sqlSession != null){ //关闭SqlSession对象 sqlSession.close(); //分离当前线程与SqlSession的关系 threadLocal.remove(); } } //测试 public static void main(String[] args) { SqlSession sqlSession = MyBatisUtil.getSqlSession(); Connection conn= sqlSession.getConnection(); System.out.println(conn != null ?"连接成功":"连接失败"); } }
mybatis.cfg.xml文件
<?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> <!-- 设置一个默认的环境信息 --> <environments default="mysql_developer"> <!-- 连接MySQL环境信息 --> <environment id="mysql_developer"> <!-- MyBatis使用jdbc事务管理器 --> <transactionManager type="jdbc"/> <!-- MyBatis使用连接池方式来获取连接对象 --> <dataSource type="pooled"> <!-- 配置与数据库交互的4个必要属性 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="mysqladmin"/> </dataSource> </environment> <!-- 连接Oracle环境信息 --> <environment id="oracle_developer"> <!-- MyBatis使用jdbc事务管理器 --> <transactionManager type="jdbc"/> <!-- MyBatis使用连接池方式来获取连接对象 --> <dataSource type="pooled"> <!-- 配置与数据库交互的4个必要属性 --> <property name="driver" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/> <property name="username" value="scott"/> <property name="password" value="tiger"/> </dataSource> </environment> </environments> <!-- 加载映射文件 --> <mappers> <mapper resource="one2one/CardMapper.xml"/> <mapper resource="one2one/StudentMapper.xml"/> </mappers> </configuration>
Card.java和Student.java
package one2one; import java.io.Serializable; /** * 身份证 * @author Administrator * */ @SuppressWarnings("serial") public class Card implements Serializable{ private Integer cid; private String num; public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getNum() { return num; } public void setNum(String num) { this.num = num; } } package one2one; import java.io.Serializable; /** * 学生 * @author Administrator * */ @SuppressWarnings("serial") public class Student implements Serializable{ private Integer sid; private String sname; private Card card; public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Card getCard() { return card; } public void setCard(Card card) { this.card = card; } }
Card.java的映射文件CardMapper.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="cardNameSpace"> <resultMap type="one2one.Card" id="cardMap"> <id column="cid" property="cid"/> <result column="num" property="num"/> </resultMap> </mapper>
Student.java类对应的映射文件StudentMapper.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="studentNameSpace"> <resultMap type="one2one.Student" id="studentMap"> <id column="sid" property="sid"/> <result column="sname" property="sname"/> <!-- 引入CardMapper.xml文件中的映射信息 property表示Student的关联属性 --> <association property="card" resultMap="cardNameSpace.cardMap"/> </resultMap> <select id="findById" parameterType="integer" resultMap="studentMap"> select s.sid,s.sname,c.cid,c.num from student s,card c where s.scid = c.cid and s.sid = #{sid} </select> <select id="findByName" parameterType="string" resultMap="studentMap"> select s.sid,s.sname,c.cid,c.num from student s,card c where s.scid = c.cid and s.sname = #{sname} </select> </mapper>
持久层类StudentCardDAO.java类
package one2one; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import util.MyBatisUtil; /** * 持久层 * @author Administrator * */ public class StudentCardDAO { /** * 查询1号学生的信息与身份证信息 * @param id * @return * @throws Exception */ public Student findById(Integer id) throws Exception{ SqlSession sqlSession = null; try { sqlSession = MyBatisUtil.getSqlSession(); return sqlSession.selectOne("studentNameSpace.findById", id); } catch (Exception e) { e.printStackTrace(); throw e; }finally{ MyBatisUtil.closeSqlSession(); } } /** * 查询“哈哈”学生的信息与身份证信息 * @param name * @return * @throws Exception */ public Student findByName(String name) throws Exception{ SqlSession sqlSession = null; try { sqlSession = MyBatisUtil.getSqlSession(); return sqlSession.selectOne("studentNameSpace.findByName", name); } catch (Exception e) { e.printStackTrace(); throw e; }finally{ MyBatisUtil.closeSqlSession(); } } //测试 查询1号学生的信息与身份证信息 @Test public void testFindById() throws Exception{ StudentCardDAO dao = new StudentCardDAO(); Student student = dao.findById(1); System.out.println(student.getSid()+":"+student.getSname()+":"+student.getCard().getNum()); } //测试 查询“哈哈”学生的信息与身份证信息 @Test public void testFindByName() throws Exception{ StudentCardDAO dao = new StudentCardDAO(); Student student = dao.findByName("哈哈"); System.out.println(student.getSid()+":"+student.getSname()+":"+student.getCard().getNum()); } }
以上所述是小编给大家介绍的MyBatis一对一映射初识教程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
本文向大家介绍mybatis关系映射之一对多和多对一,包括了mybatis关系映射之一对多和多对一的使用技巧和注意事项,需要的朋友参考一下 本实例使用用户和订单的例子做说明: 一个用户可以有多个订单, 一个订单只对应一个用户。(其中应用到注释) 1.代码的结构 2. 建表语句: 3. 用户实体: 4. 订单实体: 5.写PersonMapper.java的接口 6. 一对多实体配置: Person
有两张数据表,其中A表的某个字段的值指向B表的主键。因为A表的任何一条记录只能对应B表的一条且唯一一条记录,所以称这种 映射为A表对B表数据的一对一映射。(当然,反过来,你也可是说,是B表对A表的一对多映射)。 上述结构,如果用 POJO 来表示的话,可以参看下图: 如上图, Pet 中就可以有一个字段 master,通过自身的 masterId 指向一个 Master 对象,那么我们说 Pet.
主要内容:@OneToOne示例,程序输出结果一对一映射映射表示一个单值关联,其中一个实体的实例与另一个实体的实例相关联。在这种类型的关联中,源实体的一个实例可以映射到目标实体的一个实例。 完整的项目目录结构如下所示 - @OneToOne示例 在这个例子中,我们将创建一个学生和图书库之间的一对一关系,这样一个学生只能发放一种类型的图书。 这个例子包含以下步骤 - 第1步: 在包下创建一个实体类,在包下创建一个实体类,含学生ID()和学生姓名
问题内容: 我正在尝试在Hibernate中将一对一关系映射为“零或一个”关系。我想我可能已经找到了使用多对一方法。 A类的映射指定: B类的映射指定: 我想在数据库中找不到B的匹配行时b为null。所以我可以做到这一点(在A类中): 但是,看来b永远不会为空。 我该怎么办? 问题答案: 答案是在A中的多对一语句中添加not-found =“ ignore”: 我尝试按照Rob H的建议,简单地向
有两张数据表,其中A表的某个字段的值指向B表的主键。因为B表的任何一条记录理论上可以对应A表的多条记录,所以称这种 映射为B表对A表数据的一对多映射。 上述结构,如果用 POJO 来表示的话,可以参看下图: 如上图,一个 Master 自然就能对应多个 Pet ,所以, Master.pets (一个 List<Pet>) 就可以指向多个 Pet 对象, 那么我们说 Master.pets 就是
如何定义两个类之间的< code >一对一关系?我想我在某个地方出了问题,在概念上。我不知道是什么,但确实是。 让我们假设有两个类命名为 和 : 现在对于一个国家来说,只能有一个PM,PM只能属于一个国家。如何在映射文件中执行此操作? 我在尝试这个: 但是这种有效的映射只会在运行时产生异常。它说属性在类中找不到!但是它在类中搜索吗?它应该在类中搜索。 也帮我完成这两个类之间的< code >一对一