3 Star 2 Fork 54

Albert / JavaCore 教学项目

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

JavaCore 教学项目

项目介绍

基于JDK10的Java基础教学项目

教学项目任务细分

1,数据库准备任务

掌握Oracle数据库的安装、基本的运行等操作。

2,使用JDBC连接数据库

要求可以进行简单的查询操作,会使用Connection、DriverManger、PreparedStatement、ResultSet等类。

3,创建DBConnection工具类

创建该类,并将该类升级成拥有软编码的技术的工具类。

4,User表的创建和CRUD

学会在Oracle中创建基本表,并插入数据。

使用JDBC和DBConnection工具类,完成对user表的CRUD操作。

了解domain和手动的ORM操作的基本原理和使用方式。

5,创建JDBC操作模板

在第4个任务过程中,抽象出更多的JDBC操作模板。生成专门的数据库访问工具类:JdbcTemplate.java

1,实现专门的增、删、改方法,其方法原型如下:

public int update(String sql,Object...params); 

2,实现专门的查询方法,其方法原型如下:

public <T> T query(String sql,ResultSetHandler rsh,Object...params);

ResultSetHandler接口

public interface ResultSetHandler<T>{
    public T handler(ResultSet rs);
}

支线任务

在Users表中查询姓名中包含某个字的同学或者是姓某个姓的同学。这里需要用到like运算符和%运算符。在PreparedStatement中如何操作?

6,有关JDBC的高级操作

批量操作API。

新增数据时获取主键。

JDBC时间操作API:JDK8之前;JDK8之后

分支任务

创建一个表:

--日期时间操作
create table dateTable(
       id number(10) primary key,
       dateColumn date,				--日期
       timeColumn date,				--时间
       timestampColumn timestamp	--时间戳
);
create sequence dateTable_id start with 0 minvalue 0 increment by 1;

分别用JDK8之前的代码和JDK8之后的代码实现以上表的插入和获取操作。

7,应用任务——火车售票系统

利用任务5创建的JDBC操作模板,使用命令行界完成,完成如下任务。

一、功能需求:

查询功能

分为对车次信息的查询和客户对已订车票信息的查询。要求:

1)对车次的查询,可以按照发车车次进行查询;

2)车次信息包括:车次(可选)、出发地、目的地、发车日期(可选);

3)车次信息只允许用户查询,不允许修改。

售票功能

通过查询系统,客户找到自己满意的车次,再输入个人信息后直接通过系统进行车票的预定。要求:售票记录包括:姓名、车号、发车日期、订票日期、订票数量、总价。

退票

可退票,通过查询系统,客户可以根据自己的名字找到自己的订票信息,通过退票模块退掉已购的车票。

二、数据库表:

  1. 车次信息包括:id、车号(trainId)、出发地(to)、目的地(from)、发车日期(date)、开车时刻(time)、票价(fares)。
  2. 用户信息包括:id、用户名、密码、性别、身份证号(id number)、电话(phone)。
  3. 售票记录包括:订单号(id)、用户id、车号(trainId)、订购日期(buyDate)、订票数量(ticketNumber)、总价(totalFares)。

三、软件基本架构

CUI层,与用户进行命令行的交互。 Service层,业务数据处理。 DBOperation层,访问数据库。

查询车次功能的基本流程:进入车次查询,依次输入相应的查询关键字(注意:出发地、目的地、发车日期必须输入;车号、票价可选)。

8,应用任务——生产者与消费者

经典多线程任务

1,synchronized

基于synchronized关键字的生产者与消费者问题的任务细分

1,确定参与操作的对象有哪些? 仓库,Storage类,从生产者接收产品,并存放入仓库;同时随时准备给消费者产品。 产品,Product类,操作的对象,本身没有专门的特性。能简单区分就行了。 生产者,Producer类,生产产品,放入仓库,数量可以指定。 消费者,Customer类,从仓库销费产品,数量可以指定。

2,将仓库抽象成list集合,用于存放数据;将生产和消费抽象成两个方法。

public class Storage {

	public final int MAX_NUM=100;
	LinkedList<Product> list=new LinkedList<>();
	
	public void produce(int number) {}
	public void buy(int number) {}
}

3,生产行为详细描述

public void produce(int number) {
    synchronized(list) {	//给共享数据加锁
        while(list.size()+number>=MAX_NUM) {	//此处的逻辑是if,但必须使用while。
            System.out.println("仓库已满,无法生产产品!");
            try {
                list.wait();	//条件不被满足,等待。
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=0;i<number;i++) {
            list.add(new Product(i,Thread.currentThread().getName()+"_"+i));
        }
        System.out.println("已经生产了"+number+"件产品,仓库中共有"+list.size()+"件产品");
        list.notifyAll();	//生产结果,唤醒可能的因为仓库存货不足而挂起的线程。
    }
}

解析:

使用while代替if语句,是判断wait()方法可否执行的关键。这是因为,当某个线程被唤醒的时候,使其被挂起的条件不一定被满足。需要重复判定。所以要用while循环代替if语句。

4,生产者、消费者为两个继承了Thread类的类,需要实现核心方法public void run()

5,创建Test类,构造多个生产者和消费者从而测试多个生产者和消费者之间的消息通讯机制。

2,Lock&ReentrantLock

任务细分

1,重构,提取原来仓库类中的核心数据结构和方法原型,抽象到更高层次的接口中。如下:

public interface Storage {
	public final int MAX_NUM=100;
	LinkedList<Product> list=new LinkedList<>();
	
	public void produce(int number);
	public void buy(int number);
}
原来的仓库类,改名为StorageForSynchronized类,实现Storage接口。

加入新的Storage接口的实现类:StorageForReentrantLock类。

2,实现基于重入锁的生产者和消费者问题。这里只关注消费行为的实现。如下:

public void buy(int number) {
    lock.lock();	//加锁
    try {
        while(list.size()-number<=0) {		
            System.out.println("仓库存货不足,无法销费!");
            try {
                empty.await();		//挂起
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=0;i<number;i++) {
            list.remove();
        }
        System.out.println("已经销费了"+number+"件产品,仓库中还有"+list.size()+"件产品");
        full.signal();			//唤醒
    }finally {
        lock.unlock();			//解锁
    }
}

解析:注意特殊的语句结构,在lock.lock()方法之后的代码,必须放在try语句中,而对应的lock.unlock()方法必须放置在finally语句。这并不是为了获取某个异常,只是为了在异常可能发生时,保证一定要解锁。

9,应用任务——IO读写任务

软件架构

Java Core、CUI

项目1,火车售票系统任务细分

火车票售票系统,简称TTS。

任务1,创建数据表

tts_userInfo表、tts_trainInfo表、tts_orderform表

任务2,建立基础开发结构

edu.yuhf.tts.cui		实施CUI界面编码。
edu.yuhf.tts.dao		数据访问模型
edu.yuhf.tts.service	业务模型

任务3,抽象数据访问模型

创建Dao,利用之前的JdbcTemplate类进行相应的操作。

任务4,即席查询任务

必查内容:发车地点、到达地点

可选内容:发车时间、车次

操作步骤:

1,从CUI处收集相应的关键字,并且将关键字封装到相关的类中。这里是封装到Train类中。

System.out.println("车次查询,请按照要求输入查询关键字:");
Scanner input=new Scanner(System.in);
System.out.print("出发地:");
String fromAddress=input.nextLine();
System.out.print("目的地:");
String toAddress=input.nextLine();
System.out.print("发车日期:(2018-08-23)");
String date=input.nextLine();
System.out.print("车次");
String trainId=input.nextLine();
//jdk1.8之后的日期处理方式
Train train=null;
if(!Objects.equals(date, "")) {
    DateTimeFormatter dft=DateTimeFormatter.ofPattern("yyyy-MM-dd");
    train=new Train(0,trainId,fromAddress,toAddress,LocalDate.parse(date,dft),null,null);
}else {
    train=new Train(0,trainId,fromAddress,toAddress,null,null,null);
}

List<Train> list=queryService.queryTrain(train);

2,传递给Service组件,进行必要的业务处理。这里没有进行任何业务处理。

return queryDao.queryTrain(train);

3,再传递到Dao组件中,在该组件中根据参数对SQL语句和装入到JdbcTemplate中的入参进行拼装,并执行、返回结果。

public List<Train> queryTrain(Train train){
    //拼装SQL
    String sql="select * from tts_trainInfo " + 
        "where fromAddress=? and toaddress=?";
    if(train.getTrainId().length()!=0) {
        sql+=" and trainId=?";
    }
    if(null!=train.getDate()) {
        sql+=" and startdate=to_date(?,'yyyy-mm-dd')";
    }

    //组装参数
    List<Object> params=new ArrayList<>();
    params.add(train.getFromAddress());
    params.add(train.getToAddress());

    if(train.getTrainId().length()!=0) {
        params.add(train.getTrainId());
    }
    if(null!=train.getDate()) {
        DateTimeFormatter dft=DateTimeFormatter.ofPattern("yyyy/MM/dd");
        params.add(dft.format(train.getDate()));
    }		

    List<Train> list=JdbcTemplate.query(sql, (rs)->{
        List<Train> list0=new ArrayList<>();
        try {
            while(rs.next()) {
                Train train0=new Train(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),rs.getDate(5).toLocalDate(),rs.getTime(6).toLocalTime(),rs.getBigDecimal(7));
                list0.add(train0);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list0;
    }, params.toArray());
    return list;
}

任务5,购票任务

依然使用车次查询功能,查到具体某个车次,可以录入该车次,从而选择购买该车次的车票。

编程逻辑分析:

购票任务本质上是对订单表进行一个插入操作。而一次订单表插入操作需要同时获得车次表中的信息和用户信息。

车次信息在查询已经获得,需要得到只是用户信息。

用户信息的获取途径:1,当用户没有登录的时候,在购票之前让用户登录;2,用户已经登录了,直接使用相关信息就可以。

任务6,退票

参与贡献

  1. Fork 本项目
  2. 新建 Feat_xxx 分支
  3. 提交代码
  4. 新建 Pull Request

空文件

简介

取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/thelongestday/javacore_teaching_project.git
git@gitee.com:thelongestday/javacore_teaching_project.git
thelongestday
javacore_teaching_project
JavaCore 教学项目
master

搜索帮助