0%

11.2 注解的使用示例2 一对一关联关系

11.2 注解的使用示例2 一对一关联关系

目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
E:\workspace_web2\MyAOneToOneTest
├─src
│ ├─db.properties
│ ├─domain
│ │ ├─Card.java
│ │ └─Person.java
│ ├─fractory
│ │ └─SqlSessionFratoryTools.java
│ ├─log4j.xml
│ ├─mapper
│ │ ├─CardMapper.java
│ │ └─PersonMapper.java
│ ├─mybatis-config.xml
│ ├─mybatis_tb_card_tb_person.sql
│ └─test
│ └─OneToOneTest.java
└─WebContent
├─META-INF
└─WEB-INF
└─lib
├─ant-1.9.6.jar
├─ant-launcher-1.9.6.jar
├─asm-5.2.jar
├─cglib-3.2.5.jar
├─commons-logging-1.2.jar
├─javassist-3.22.0-CR2.jar
├─log4j-1.2.17.jar
├─log4j-api-2.3.jar
├─log4j-core-2.3.jar
├─mybatis-3.4.5.jar
├─mysql-connector-java-5.1.44-bin.jar
├─ognl-3.1.15.jar
├─slf4j-api-1.7.25.jar
└─slf4j-log4j12-1.7.25.jar

创建数据库表

首先,给之前创建的mybatis数据库创建两个表tb_cardtb_person,并插入测试数据。SQL脚本如下使用方式:
保存成.sql文件,然后使用Navicat导入(设置编码格式utf-8,免得乱码).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 创建tb_card表
DROP TABLE IF EXISTS `tb_card`;
CREATE TABLE `tb_card` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(18) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 插入一条数据
INSERT INTO `tb_card` VALUES ('1', '43280119980091');
# 创建tb_person表
DROP TABLE IF EXISTS `tb_person`;
CREATE TABLE `tb_person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(18) NOT NULL,
`sex` varchar(18) NOT NULL,
`age` int(11) DEFAULT NULL,
`card_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `card_id` (`card_id`),
CONSTRAINT `tb_person_ibfk_1` FOREIGN KEY (`card_id`)
REFERENCES `tb_card` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 插入一条数据
INSERT INTO `tb_person` VALUES ('1', '小明', '男', '22', '1');

创建持久化类

Card.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package domain;
public class Card {
private Integer id;
private String code;
public Card()
{
// TODO Auto-generated constructor stub
}
public Card(Integer id, String code)
{
this.id = id;
this.code = code;
}
// 此处省略getter和setter方法,请自己补上
@Override
public String toString()
{
return "Card [id=" + id + ", code=" + code + "]";
}
}

Person.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package domain;
public class Person {
private Integer id;
private String name;
private String sex;
private Integer age;
private Card card;
public Person()
{
super();
}
// 此处省略getter和setter方法,请自己补上
@Override
public String toString()
{
return "Person [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", card="
+ card + "]";
}
}

mapper接口

CardMapper接口

1
2
3
4
5
6
7
package mapper;
import org.apache.ibatis.annotations.Select;
import domain.Card;
public interface CardMapper {
@Select("select * from tb_card where id=#{id}")
Card selectCardById(Integer id);
}

PersonMapper接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package mapper;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import domain.Person;
public interface PersonMapper {
@Select("select * from tb_person where id=#{id}")
@Results(
{@Result(
property = "id",
column = "id",
id = true
), @Result(
property = "name",
column = "name"
), @Result(
property = "sex",
column = "sex"
), @Result(
property = "age",
column = "age"
), @Result(
property = "card",
column = "card_id",
one = @One(
select = "mapper.CardMapper.selectCardByCardID",
fetchType = FetchType.EAGER
)
)}
)
Person selectPersonById(@Param("id") Integer id);
}

selectPersonById方法使用了@Select注解,其根据id查询对应的Person数据。因为需要将Person对应的Card数据也查询出来,所以PersonCard属性使用了一个@Result结果映射。column="card_id",property="card"表示PersonCard属性对应tb_person表的card_id列,one属性表示是一个一对一关联关系,@one注解的select属性表示需要关联执行的SQL语句,fetchType表示查询的类型是立即加载(EAGER)还是懒加载(LAZY)。

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package test;
import org.apache.ibatis.session.SqlSession;
import domain.Person;
import fractory.SqlSessionFratoryTools;
import mapper.PersonMapper;
public class OneToOneTest {
public static void main(String[] args)
{
SqlSession sqlSession = null;
try
{
sqlSession = SqlSessionFratoryTools.getSqlSession();
PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
Person person = personMapper.selectPersonById(1);
System.out.println(person);
// 提交事务
sqlSession.commit();
} catch (Exception e)
{
// 出错回滚事务
sqlSession.rollback();
e.printStackTrace();
} finally
{
// 关闭会话
if (sqlSession != null)
sqlSession.close();
}
}
}

运行效果

运行OneToOneTest类的main方法,该方法通过SqlSessiongetMapper(Class<T> type)方法获得mapper接口的代理对象PersonMapper。调用PersonMapperselectPersonById方法时会执行该方法上的注解。需要注意的是,Person的一对一关联使用的注解@oneselect属性,要执行的SQL语句在CardMapper接口的selectCardById方法的注解中。控制台显示如

1
2
3
4
5
6
7
DEBUG [main] ==>  Preparing: select * from tb_person where id=? 
DEBUG [main] ==> Parameters: 1(Integer)
DEBUG [main] ====> Preparing: select * from tb_card where id=?
DEBUG [main] ====> Parameters: 1(Integer)
DEBUG [main] <==== Total: 1
DEBUG [main] <== Total: 1
Person [id=1, name=小明, sex=男, age=22, card=Card [id=1, code=43280119980091]]

可以看到,查询Peson信息时Person对应的Card对象也被查询出来了.

原文链接: 11.2 注解的使用示例2 一对一关联关系