iBATIS入门知识进阶四

一、关联数据的存储查询方式,以班级和学生为例,
在学生多方添加班级一方的引用,班级一端增加对学生集合的引用,建立双向关联

实体类
public class Classes {
private int id;
private String name;
private List students; //不可以用set否则会出错

public List getStudents() {
return students;
}
public void setStudents(List students) {
this.students = students;
}

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

public class Student {
private int id;
private String name;
private String sex;
private Classes classes;

public Classes getClasses() {
return classes;
}
public void setClasses(Classes classes) {
this.classes = classes;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}

}


Classes.xml文件信息:
	<typeAlias alias="Classes" type="com.lzh.ibatis.Classes"/>

<insert id="saveClasses" parameterClass="Classes">
insert into t_classes values (null,#name#)
<selectKey resultClass="int" keyProperty="id">
select @@identity as id//存储时必须将id返回,以备学生所用
</selectKey>
</insert>

<resultMap class="Classes" id="classes-result">
<result property="id"/>
<result property="name" column="cname"/>
<result property="students" column="id" select="findStudentByCid"/>
</resultMap>

<select id="findClassesById" resultMap="classes-result" parameterClass="int">
select * from t_classes where id=#id#
</select>

<select id="findClasses" resultMap="classes-result" parameterClass="int">
select * from t_classes where id=#id#
</select>


Student.xml文件:
	<typeAlias alias="Student" type="com.lzh.ibatis.Student"/>

<insert id="saveStudent" parameterClass="Student">
insert into t_student values (null,#name#,#sex#,#classes.id#)
</insert>

<resultMap class="Student" id="findStudent-result">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="classes" column="cid" select="findClassesById"/>
</resultMap>

<select id="findStudent" resultMap="findStudent-result" parameterClass="int">
select * from t_student where id=#id#
</select>

<select id="findStudentByCid" resultMap="findStudent-result" parameterClass="int">
select * from t_student where cid=#cid#
</select>

在sqlMapConfig.xml文件增加上面这两个映射文件,为了是大家能更清楚,xml文件中所变化的内容,我将xml文件全部贴出:
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig SYSTEM "http://ibatis.apache.org/dtd/sql-map-config-2.dtd" >
<sqlMapConfig>
<settings lazyLoadingEnabled="true"/>
<transactionManager type="JDBC" commitRequired="false">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/>
<property name="JDBC.ConnectionURL" value="jdbc:mysql://127.0.0.1/ibatis"/>
<property name="JDBC.Username" value="root"/>
<property name="JDBC.Password" value="123"/>
</dataSource>
</transactionManager>
<sqlMap resource="com/lzh/ibatis/Student.xml"/>
<sqlMap resource="com/lzh/ibatis/Classes.xml"/>
</sqlMapConfig>


利用上面的方式,是可以实现的,不过需要明白为什么可以,如果在上面的xml配置文件中不增加lazyLoadingEnabled="true",程序将会陷入死循环,值栈溢出,同时集合映射时也必须指定为list,而无法使用set集合。
因此实现双向关联,需要完成下面两步操作

* 【双向关联】如果没有启用懒加载,将会出现StackOverFlow的异常!在设置lazyLoadingEnabled="true"(上面的xml文件中可以看到)
* 【双向关联】启用懒加载特性,而且将关联的集合定义为Set,无法进行双向关联定义(但定义成List就可以)

测试代码:
public void testSaveStudent()throws Exception{

SqlMapClient sqlMapper = IbatisSQLMapConfig.getSqlMapInstance();
Classes classes = new Classes();
classes.setName("测试班级"+ new Random().nextInt(9999));
sqlMapper.insert("saveClasses", classes);
Student student = new Student();
student.setName("学生"+new Random().nextInt(9999));
student.setSex("男");
student.setClasses(classes);
sqlMapper.insert("saveStudent",student);
}

public void testFindClasses()throws Exception{

SqlMapClient sqlMapper = IbatisSQLMapConfig.getSqlMapInstance();

Classes cla = (Classes)sqlMapper.queryForObject("findClasses",1);
System.out.println(cla.getName()+"有学生人数:"+cla.getStudents().size());
}

public void testFindStudent()throws Exception{

SqlMapClient sqlMapper = IbatisSQLMapConfig.getSqlMapInstance();

Student stu = (Student)sqlMapper.queryForObject("findStudent",1);
System.out.println(stu.getName()+"所属班级是:"+stu.getClasses().getName());
}

下面来贴出sql语句:
CREATE TABLE t_student(
id integer not null auto_increment,
name varchar(255),
sex varchar(255),
cid integer,
primary key(id)
);

CREATE TABLE t_classes(
id integer not null auto_increment,
cname varchar(255),
primary key(id)
)


二、多态查询的映射策略

在设计数据库表的时候,需要提供一个辨别字段,来记录对象的类型,在插入数据的时候,我们要自己定义这个辨别字段的值,在查询数据的时候可以利用iBATIS提供的discriminator元素来映射多态的数据。
下面来贴出实体类代码:
/**
* 基类
* @author Administrator
*
*/
public class Animal {
private int id;
private String name;
private String sex;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
/**
* Bird子类
* @author Administrator
*/
public class Bird extends Animal{
private int height;

public int getHeight() {
return height;
}

public void setHeight(int height) {
this.height = height;
}
}
/**
* Pig子类
* @author Administrator
*/
public class Pig extends Animal{
private int weight;

public int getWeight() {
return weight;
}

public void setWeight(int weight) {
this.weight = weight;
}
}
下面贴出Animal.xml配置文件的信息:
<sqlMap>
<typeAlias alias="Animal" type="com.lzh.ibatis.Animal"/>
<typeAlias alias="Bird" type="com.lzh.ibatis.Bird"/>
<typeAlias alias="Pig" type="com.lzh.ibatis.Pig"/>

<insert id="insertAnimal" parameterClass="Animal">
insert into t_animal (name,sex,animal_type) values (#name#,#sex#,'Animal')
</insert>
<insert id="insertBird" parameterClass="Bird">
insert into t_animal (name,sex,height,animal_type) values (#name#,#sex#,#height#,'Bird')
</insert>
<insert id="insertPig" parameterClass="Pig">
insert into t_animal (name,sex,weight,animal_type) values (#name#,#sex#,#weight#,'Pig')
</insert>

<resultMap class="Animal" id="animal">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<discriminator column="animal_type" javaType="string">
<subMap value="Bird" resultMap="bird"/>
<subMap value="Pig" resultMap="pig"/>
</discriminator>
</resultMap>
<resultMap class="Bird" id="bird" extends="animal">
<result property="height" column="height"/>
</resultMap>
<resultMap class="Pig" id="pig" extends="animal">
<result property="weight" column="weight"/>
</resultMap>
<select id="findAllAnimals" resultMap="animal">
select * from t_animal
</select>
</sqlMap>


在sqlMapConfig.xml文件中增加下面的映射
  <sqlMap resource="com/lzh/ibatis/Animal.xml"/>


测试代码:
public void testSaveAnimal() throws Exception{

//从配置文件中得到SqlMapClient对象
SqlMapClient sqlMapper = IbatisSQLMapConfig.getSqlMapInstance();

Animal a = new Animal();
a.setName("动物");
a.setSex("1");
sqlMapper.insert("insertAnimal", a);

Bird b = new Bird();
b.setName("鸟");
b.setSex("0");
b.setHeight(1000);
sqlMapper.insert("insertBird", b);

Pig p = new Pig();
p.setName("猪");
p.setSex("1");
p.setWeight(500);
sqlMapper.insert("insertPig", p);
}

public void testFindAllAnimals() throws Exception{

//从配置文件中得到SqlMapClient对象
SqlMapClient sqlMapper = IbatisSQLMapConfig.getSqlMapInstance();;

List animals = sqlMapper.queryForList("findAllAnimals");
for (Iterator iterator = animals.iterator(); iterator.hasNext();) {
Animal a = (Animal) iterator.next();
System.out.println(a.getName()+","+a);
}
}

sql建表语句:
create table t_animal(
ID integer not null auto_increment,
NAME varchar(255),
SEX varchar(255),
HEIGHT integer,
WEIGHT integer,
ANIMAL_TYPE varchar(20),
primary key(ID)
);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值