与其说是Mybatis配置一对一,不如说是我们手动配置好数据库的表关联然后映射到Mybatis上去 这里以双向关联为例
1.设计数据表
关于一对一的设计我一般使用两种方式,入下图
一.使用唯一外键关联
即在任意一张表中添加外键参照对方表的主键,并设置Unique属性, 不过这种方式有个缺点,参照表的Null值只能有一个,在一些特殊情况下不合适
二.主键同时作为外键
优点是可以少设计一列,空间被省下来了,但 是必须要依赖对方表的主键
这里以第一种方式建两张表
CREATE TABLE t_person (
p_id int IDENTITY(1,1),
p_name VARCHAR(20),
P_birth DateTime,
PRIMARY KEY(p_id)
)
CREATE TABLE t_idcard(
c_id int IDENTITY(1,1),
c_number VARCHAR(30),
c_jiguan VARCHAR(30),
c_p_id int UNIQUE,
PRIMARY KEY(c_id),
FOREIGN KEY(c_p_id) REFERENCES t_person(p_id)
)
2.设计实体对象
实体对象是其中最简单的一步 如下:
public class Person {
private Integer PersonID;
private String Name;
private Date Birth;
private IDCard idcard;
}
public class IDCard {
private Integer ID;
private String IDNumber;
private String jiguan;
private Person owner;
}
3.完成Mapper接口(简单写几个方法)
public interface PersonMapper {
Person getPersonByID(Integer ID);
List<Person> getAll();
void CreateNewPerson(Person person);
}
public interface IDCardMapper {
IDCard getIDCardByID(Integer ID);
List<IDCard> getAllIDCard();
void CreateIDCard(IDCard card);
}
4.完成XML映射配置
PersonMapper的配置文件
<?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="OneToOne.PersonMapper">
<resultMap type="OneToOne.Person" id="PersonMap">
<id column="p_id" property="PersonID"/>
<result column="p_name" property="Name"/>
<result column="p_birth" property="Birth"/>
<association property="idcard" javaType="OneToOne.IDCard">
<id column="c_id" property="ID"/>
<result column="c_number" property="IDNumber"/>
<result column="c_jiguan" property="jiguan"/>
</association>
</resultMap>
<select id="getPersonByID"
parameterType="integer"
resultMap="PersonMap">
SELECT * from t_person p left join t_idcard id on p.p_id = id.c_p_id where p.p_id =#{ID}
</select>
<select id="getAll" resultMap="PersonMap">
Select p.*,id.c_id,id.c_number,id.c_jiguan from t_person p,t_idcard id where p.p_id = id.c_p_id
</select>
<insert id="CreateNewPerson" parameterType="OneToOne.Person">
insert into t_person values(#{Name},#{Birth})
</insert>
</mapper>
IDCardMapper.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="OneToOne.IDCardMapper">
<resultMap type="OneToOne.IDCard" id="IDCardMap">
<id column="c_id" property="ID"/>
<result column="c_number" property="IDNumber"/>
<result column="c_jiguan" property="jiguan"/>
<association property="owner" javaType="OneToOne.Person">
<id column="p_id" property="PersonID"/>
<result column="p_name" property="Name"/>
<result column="p_birth" property="Birth"/>
</association>
</resultMap>
<select id="getIDCardByID"
resultMap="IDCardMap"
parameterType="integer">
Select * from t_idcard id,t_person p where p.p_id = id.c_p_id and id.c_p_id = #{ID}
</select>
<select id="getAllIDCard" resultMap="IDCardMap">
Select * from t_idcard id,t_person p where p.p_id = id.c_p_id;
</select>
<insert id="CreateIDCard"
parameterType="OneToOne.IDCard">
insert into t_idcard values(#{IDNumber},#{jiguan},#{owner.PersonID})
</insert>
</mapper>
5.测试
先向主表插入一条数据
public static void main(String[] args) throws IOException {
InputStream input = Resources.getResourceAsStream("MyBatisCFG.xml");
SqlSessionFactory factory = (new SqlSessionFactoryBuilder()).build(input);
SqlSession Session = factory.openSession();
PersonMapper personmapper = Session.getMapper(PersonMapper.class);
Person person = new Person();person.setName("HJXSB");
person.setBirth(new Date(1999,6,8));
mapper.CreateNewPerson(person);
Session.Commit();
Session.Close();
}
再插入IDCard对象
public static void main(String[] args) throws IOException {
InputStream input = Resources.getResourceAsStream("MyBatisCFG.xml");
SqlSessionFactory factory = (new SqlSessionFactoryBuilder()).build(input);
SqlSession Session = factory.openSession();
PersonMapper personmapper = Session.getMapper(PersonMapper.class);
IDCardMapper mapper = Session.getMapper(IDCardMapper.class);
IDCard cardOne = new IDCard();
cardOne.setIDNumber("6020182100");
cardOne.setJiguan("JX fuzhuo nancheng");
cardOne.setOwner(personmapper.getPersonByID(1));
mapper.CreateIDCard(cardOne);
Session.commit();
Session.close();
}
查看一下日志:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 635611994.
DEBUG [main] - Setting autocommit to false on JDBC Connection [ConnectionID:1 ClientConnectionId: 36df4f8f-e243-43ab-90cd-b28742d1beba]
DEBUG [main] - ==> Preparing: SELECT * from t_person p left join t_idcard id on p.p_id = id.c_p_id where p.p_id =?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
DEBUG [main] - ==> Preparing: insert into t_idcard values(?,?,?)
DEBUG [main] - ==> Parameters: 6020182199(String), JX nanchang(String), 1(Integer)
再单独查出来看看
System.out.println(mapper.getIDCardByID(1));
日志:
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 635611994.
DEBUG [main] - Setting autocommit to false on JDBC Connection [ConnectionID:1 ClientConnectionId: 30529fe9-fe4b-4a6e-bba1-c61c85f15788]
DEBUG [main] - ==> Preparing: Select * from t_idcard id,t_person p where p.p_id = id.c_p_id and id.c_p_id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
IDCard [ID=1, IDNumber=6020182100, jiguan=JX fuzhuo nancheng, owner=Person [PersonID=1, Name=HJXSB, Birth=Sat Jul 08 00:00:00 CST 3899, idcard=null]]
当我们想再次关联已设置关联的对象时(破坏一对一时)
public static void main(String[] args) throws IOException {
InputStream input = Resources.getResourceAsStream("MyBatisCFG.xml");
SqlSessionFactory factory = (new SqlSessionFactoryBuilder()).build(input);
SqlSession Session = factory.openSession();
PersonMapper personmapper = Session.getMapper(PersonMapper.class);
IDCardMapper mapper = Session.getMapper(IDCardMapper.class);
IDCard cardOne = new IDCard();
cardOne.setIDNumber("6020182199");
cardOne.setJiguan("JX nanchang");
cardOne.setOwner(personmapper.getPersonByID(1));
mapper.CreateIDCard(cardOne);
Session.commit();
Session.close();
}
显然会报错:
Error updating database. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 違反 UNIQUE KEY 條件約束 'UQ__t_idcard__FFF1E039C1790658'。無法在物件 'dbo.t_idcard' 中插入重複的索引鍵。重複的索引鍵值是 (1)。
### The error may exist in Mappers/IDCardMapper.xml
### The error may involve OneToOne.IDCardMapper.CreateIDCard-Inline
### The error occurred while setting parameters
### SQL: insert into t_idcard values(?,?,?)
### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 違反 UNIQUE KEY 條件約束 'UQ__t_idcard__FFF1E039C1790658'。無法在物件 'dbo.t_idcard' 中插入重複的索引鍵。重複的索引鍵值是 (1)。
PS: 当你引入日志框架设置了配置文件后就可以显示日志了,本例使用的是logback,配置文件 如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%5level [%thread] - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="stdout"/>
</root>
</configuration>
|