一对一
步骤: 导mysql 的 jar包,及工具类
自己创建连接数据库的工具类 DBTools
通过面向接口设计程序的方式来编程
SQL创建表
- 创建学生表
create table student(
sid int primary key auto_increment,
stuName varchar(22),
address varchar(22)); - 创建信息表
create table info(
id int primary key auto_increment,
code
varcahr(22),
address varchar(22),
sid int,
foreign key(sid) references student(sid));
表之间的关系是 一对一。
创建实体并映射
- 并非通过在实体中添加不属于本实体的属性来映射的 只是为了方便通过本实体通过 访问器的方式去访问主表。 创建实体是直接代码表示,且从表中有外键。
- toString()只是打印本类的属性和方法 不能添加 非本类的属性 及使用toString要在映射之前。
- 每次映射后 ,及 Info表中添加private Student student;属性和改访问器 这是通过从表查询主表的时候用的 若不考虑逻辑;通过学生查询他的身份证,则需要返回的类型是Student 在通过访问器的方式返回 info实体。
- 映射在从表和主表都可以,取决于
通过主表找从表 映射在主表
通过从表找主表 映射在从表 - 面向接口编程的思想
一. 实体表
package www.oracle.vo;
public class Student {
private Integer sid;
private String stuName;
private String password;
private Info info;
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", stuName=" + stuName + ", password=" + password + "]";
}
}
package www.oracle.vo;
public class Info {
private Integer id;
private String code;
private String address;
private Integer sid;
private Student studnet;
public Student getStudnet() {
return studnet;
}
public void setStudnet(Student studnet) {
this.studnet = studnet;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
@Override
public String toString() {
return "Info [id=" + id + ", code=" + code + ", address=" + address + ", sid=" + sid + "]";
}
}
二.接口
package www.util.dao;
import www.oracle.vo.Info;
public interface InfoDao {
public Info getStudentByInfoCode(String code) throws Exception;
}
三.接口的实现类
package www.util.daoImpl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import www.oracle.util.DBTools;
import www.oracle.vo.Info;
import www.oracle.vo.Student;
import www.util.dao.InfoDao;
// 建立级联查询 一对一 是通过一个类中包含一个私有类, 通过从表(或主表)查询主表(从表),返回值类型是从表(主表)的类型;从表的类型在创建对象获得他的属性 主表 及 info.getStudent() 来获取主表的对象
// 通过 主表查询从表,返回的类型是主表的类型;在通过返回的对象来获得从表的属
//-----重要:级联查询是通过 俩实体表中互相映射来模拟外键的
/*1. 通过 Info 查询 Student 返回一个Info实体;在 Info a=new Info(); a.getStudent() 获取Stduent实体
*2. 通过 Student 查询 Info 返回一个 Student实体 在 Student a=new Student(); a.getInfo();的方式获取 Info实体
*
* */
public class InfoDaoImpl implements InfoDao {
@Override
public Info getStudentByInfoCode(String code) throws Exception {
// TODO Auto-generated method stub
String sql="select * from info i inner join student s on i.sid=s.sid where i.`code` = ?";
Connection conn= DBTools.getConnection();
PreparedStatement ps= conn.prepareStatement(sql);
ps.setString(1, code);
ResultSet rs=ps.executeQuery();
Info info=null;
Student student=null;
while(rs.next()) {
info =new Info();
student= new Student();
info.setAddress(rs.getString("address"));
info.setCode(rs.getString("code"));
info.setId(rs.getInt("id"));
info.setSid(rs.getInt("sid"));
student.setPassword(rs.getString("password"));
student.setSid(rs.getInt("sid"));
student.setStuName(rs.getString("stuName"));
info.setStudnet(student);
}
return info;
}
}
//TODO Auto-generated method stub
// TODO Auto-generated method stub
// TODO Auto-generated method stub
// 根据 info表找学生信息 外键在从表info中 一般逻辑上都是从表找主表 通过外键查询主表
/* 一对一 外键在主表或从表都可
* select * from info a 从表 info a
* inner join student b 主表 student b
* on a.sid=b.sid 可以看出是等值连接
* where a.`code`='9527'; 查询条件根据从表的`code` 来查找
*
*
* */
四. 测试类
package www.oracle.test;
import org.junit.Test;
import www.oracle.vo.Info;
import www.oracle.vo.Student;
import www.util.dao.InfoDao;
import www.util.daoImpl.InfoDaoImpl;
public class TestInfo {
InfoDao info =new InfoDaoImpl();
// 根据info表 查询 学生 返回的是 info的类型 通过info对象来获取本类中的学生属性 这是映射 要注意的是, 表实体类内的toString不能打印映射属性的 但是可以打印外键
// 在赋值的代码中可以看出 通过info表查询学生 不需要在 学生实体中加映射;因为映射就是为了通过改实体获得映射对象的实体信息 故 不需要在Student实体中写 private Info info;这行映射代码
@Test
public void getInfo() throws Exception {
String code="9567";
Info a=info.getStudentByInfoCode(code);
Student student=a.getStudnet();
System.out.println(student);
}
}
总结–模型层
www.oracle.vo 实体包
www.oracle.util 工具包
www.oracle.dao 接口包
www.oracle.daoImpl 实现类包
www.oracle.test 测试包
www.oracle.constant 常量包
- 需要手动导入 mysql的jar包来用,这是官方写的 我们不知道内部源码 直接用
- 测试包好导入 直接就导入了 不需要像jar包那样麻烦
- 最难的是实现类怎么写
- sql语句的级联查询 一般根据谁查谁就是主表
select * from info a -----------------主表
inner join studnet b ------------------从表
on a.sid=b.sid -----------------等职查询
where a.code
=‘ ’;------------------
一对多中的反向是一对一
order不加着重 关键字当作表来使用
理解:一对多是指多方中的一个也是和这个主表有联系 及一对一。
-----------------------------重要 ----------------------
sql语法错误: 以默认关键字不加着重的方式来当作表查询
select * from order
o
inner join student s
on o.sid=s.sid -----------------------------正确
where o.oid=5;
select * from order o inner join student s on o.sid=s.sid where o.oid= ? ------------------------------------------------------------------------------------ 错误
错误代码
package www.oracle.daoImpl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import www.oracle.dao.OrderDao;
import www.oracle.util.DBTools;
import www.oracle.vo.Order;
import www.oracle.vo.Student;
public class OrderDaoImpl implements OrderDao {
@Override
public Order getStudentByOrder(int id) throws Exception {
// TODO Auto-generated method stub //-------------------------------重要
String sql="select * from order o inner join student s on o.sid=s.sid where o.oid= ?";// 注意 根据order表找学生 是一对一 应根据的查询位置是 order表的id才可以
Connection conn=DBTools.getConnection(); // 老师写的一对多 是根据学生找订单 查询位置自然hi是 根据学生的sid来找 及 where sid=s.sid=?才可以
PreparedStatement ps=conn.prepareStatement(sql); // order没有加着重 所i一写sql语句环视在 Nevicat里写把 有提示
ps.setInt(1, id);
ResultSet rs=ps.executeQuery();
Order order =null;
Student student =null;
while(rs.next()) {
order=new Order();
student =new Student();
order.setCode(rs.getString("code"));
order.setCreateTime(rs.getTimestamp("createTime"));
order.setOid(rs.getInt("oid"));
order.setPrice(rs.getDouble("price"));
student.setPassword(rs.getString("password"));
student.setSid(rs.getInt("sid"));
student.setStuName(rs.getString("stuName"));
order.setStudent(student);
}
return order;
}
}
- 创建表
不知道如何用SQL语言插入 TimeStamp时间变量
create tableorder
(
oid int primary key auto_increment,
code
varchar(22),
price DOUBLE,
createTime TimeStamp, ---------TimeStamp自动获取数据库时间的时分秒
sid int,
foreign key(sid) references student(sid)); ------------------------ 外键
create table student(
sid int primary key auto_increment,
stuName varchar(22),
address varcahr(22));
表模型
2. 创建实体
package www.oracle.vo;
import java.util.List;
public class Student {
private Integer sid;
private String stuName;
private String password;
private List<Order> order;
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", stuName=" + stuName + ", password=" + password + "]";
}
}
package www.oracle.vo;
import java.sql.Timestamp;
public class Order {
private Integer oid;
private String code;
private Double price;
private Timestamp createTime;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Timestamp getCreateTime() {
return createTime;
}
public void setCreateTime(Timestamp createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Order [oid=" + oid + ", code=" + code + ", price=" + price + ", createTime=" + createTime + "]";
}
}
- 接口设计
package www.oracle.dao;
import www.oracle.vo.Order;
public interface OrderDao {
// 一对一, 一对多的反向 但是业务上一般是 学生查看自己点了哪些订单
public Order getStudentByOrder(int id) throws Exception;
}
- 导mysql的jar包 并自己设计连接数据库的工具类
设计 DBTools工具类
package www.oracle.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DBTools {
private static final String URL="jdbc:mysql://localhost:3306/test?characterEncoding=UTF8";
private static final String USER="root";
private static final String PASSWORD="root";
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
Connection conn=null;
conn =DriverManager.getConnection(URL,USER,PASSWORD);
return conn;
}
public static void close(Statement stat, ResultSet rs, Connection conn) {
try {
if(rs!=null) {
rs.close();
}
if(conn !=null) {
conn.close();
}
if(stat !=null) {
stat.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- 接口的实现类
package www.oracle.daoImpl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import www.oracle.dao.OrderDao;
import www.oracle.util.DBTools;
import www.oracle.vo.Order;
import www.oracle.vo.Student;
public class OrderDaoImpl implements OrderDao {
@Override
public Order getStudentByOrder(int id) throws Exception {
// TODO Auto-generated method stub //-------------------------------重要
String sql="select * from `order` o inner join student s on o.sid=s.sid where o.oid= ?";// 注意 根据order表找学生 是一对一 应根据的查询位置是 order表的id才可以
Connection conn=DBTools.getConnection(); // 老师写的一对多 是根据学生找订单 查询位置自然hi是 根据学生的sid来找 及 where sid=s.sid=?才可以
PreparedStatement ps=conn.prepareStatement(sql); // order没有加着重 所i一写sql语句环视在 Nevicat里写把 有提示
ps.setInt(1, id);
ResultSet rs=ps.executeQuery();
Order order =null;
Student student =null;
while(rs.next()) {
order=new Order();
student =new Student();
order.setCode(rs.getString("code"));
order.setCreateTime(rs.getTimestamp("createTime"));
order.setOid(rs.getInt("oid"));
order.setPrice(rs.getDouble("price"));
student.setPassword(rs.getString("password"));
student.setSid(rs.getInt("sid"));
student.setStuName(rs.getString("stuName"));
order.setStudent(student);
}
return order;
}
}
- 测试类
package www.oracle.test;
import org.junit.Test;
import www.oracle.dao.OrderDao;
import www.oracle.daoImpl.OrderDaoImpl;
import www.oracle.vo.Order;
import www.oracle.vo.Student;
public class TestGetStudentByOrder {
OrderDao orderDao =new OrderDaoImpl();
//一对多
/*1. 根据订单找学生 是变相的 一对一 因为一个订单只能属于一个人
* 2. 根据学生找订单 就是一对多 因为一个人可有多个订单 得到订单要返回一个集合
*
* */
// 1. 变相 一对一
@Test
public void testGetStudentByOrder() throws Exception {
Order order=orderDao.getStudentByOrder(5);
Student s=order.getStudent();
System.out.println(s);
}
//2. 一对多
@Test
public void testGetOrderByStudent() {
}
}
一对多
难点 :StudentDaoImpl实现类的设计
实现类中要设置返回的类型Student 并写赋值代码
一查多 一中的映射是一个集合 用于存储多个从表实体
- SQL 语言的设计
SQL:
select * from student s
inner join order o
on s.sid=o.sid
where s.sid=? - 创造容器承接映射对象
List orders =new ArrayList<>(); - ResultSet rs=ps.ExecuteQuery();
Student studnet=null;
Order order=null;
while(rs.next()){
student =new Student();
order =new Order();
student.set… ;
student.set…;
order.set…(rs.getString(" "));
orders.add(order);
student.setOrders(order);------------------------------ 重要
}
- 实体表代码
package www.oracle.vo;
import java.util.List;
public class Student {
private Integer sid;
private String stuName;
private String password;
private List<Order> orders;
public List<Order> getOrders() { // 映射多个从表并存储用于
return orders;
}
public void setOrders(List<Order> orders) {// 从表的访问器只有 set 没有get 我们得到结果只能读取集合
this.orders = orders;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", stuName=" + stuName + ", password=" + password + "]";
}
}
order的实体
package www.oracle.vo;
import java.sql.Timestamp;
public class Order {
private Integer oid;
private String code;
private Double price;
private Timestamp createTime;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Timestamp getCreateTime() {
return createTime;
}
public void setCreateTime(Timestamp createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Order [oid=" + oid + ", code=" + code + ", price=" + price + ", createTime=" + createTime + "]";
}
}
接口
package www.oracle.dao;
import www.oracle.vo.Student;
public interface StudentDao {
// 一对多 根据单表找多表并返回一个多表的集合 及映射在主表中的是一个存放多表的集合 通过返回这个主表的对象 在通过构造器去访问多表
public Student getOrderByStudent(int id) throws Exception;
}
实现类
package www.oracle.daoImpl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import www.oracle.dao.StudentDao;
import www.oracle.util.DBTools;
import www.oracle.vo.Order;
import www.oracle.vo.Student;
public class StudentDaoImpl implements StudentDao{
List<Order> orders =new ArrayList<>();
@Override
public Student getOrderByStudent(int id) throws Exception {
// TODO Auto-generated method stub
String sql="select * from student s inner join `order` o on s.sid=o.sid where o.sid=?";
Connection conn=DBTools.getConnection();
PreparedStatement ps= conn.prepareStatement(sql);
ps.setInt(1, id);
ResultSet rs=ps.executeQuery();
Student student =null;
Order order=null;
while(rs.next()) {
student=new Student(); //----------------------------------------------重要--------------------------------------
student.setSid(rs.getInt("sid")); // rs.所获取的是表中查询到的数据 Student类型从 student表中获取 及 sid Order类型从 Order表中查询获取 及 oid
student.setPassword(rs.getString("password"));//-----------------------------------------------------------------------------------------
student.setStuName(rs.getString("stuName"));
order =new Order();
order.setOid(rs.getInt("oid"));
order.setCode(rs.getString("code"));
order.setCreateTime(rs.getTimestamp("createTime"));
order.setPrice(rs.getDouble("price"));
orders.add(order);
student.setOrders(orders);
}
return student;
}
}
测试类
package www.oracle.test;
import java.util.List;
import org.junit.Test;
import www.oracle.dao.StudentDao;
import www.oracle.daoImpl.StudentDaoImpl;
import www.oracle.vo.Order;
import www.oracle.vo.Student;
public class TestGetOrderByStudent {
StudentDao studentDao =new StudentDaoImpl();
@Test
public void testGetOrderByStudent() throws Exception {
Student s=studentDao.getOrderByStudent(1);
List<Order> list=s.getOrders();
for(Order li_ :list) {
System.out.println(li_);
}
}
}