# JavaCore 教学项目 **Repository Path**: thelongestday/javacore_teaching_project ## Basic Information - **Project Name**: JavaCore 教学项目 - **Description**: 基于JDK10的Java基础教学项目 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 54 - **Created**: 2018-08-14 - **Last Updated**: 2025-02-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## 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,实现专门的增、删、改方法,其方法原型如下: ```java public int update(String sql,Object...params); ``` 2,实现专门的查询方法,其方法原型如下: ```java public T query(String sql,ResultSetHandler rsh,Object...params); ``` ResultSetHandler接口 ```java public interface ResultSetHandler{ public T handler(ResultSet rs); } ``` #### 支线任务 在Users表中查询姓名中包含某个字的同学或者是姓某个姓的同学。这里需要用到like运算符和%运算符。在PreparedStatement中如何操作? ### 6,有关JDBC的高级操作 批量操作API。 新增数据时获取主键。 JDBC时间操作API:JDK8之前;JDK8之后 #### 分支任务 创建一个表: ```sql --日期时间操作 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集合,用于存放数据;将生产和消费抽象成两个方法。 ```java public class Storage { public final int MAX_NUM=100; LinkedList list=new LinkedList<>(); public void produce(int number) {} public void buy(int number) {} } ``` 3,生产行为详细描述 ```java 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 list=new LinkedList<>(); public void produce(int number); public void buy(int number); } ``` 原来的仓库类,改名为StorageForSynchronized类,实现Storage接口。 加入新的Storage接口的实现类:StorageForReentrantLock类。 2,实现基于重入锁的生产者和消费者问题。这里只关注消费行为的实现。如下: ```java 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 list=queryService.queryTrain(train); ``` 2,传递给Service组件,进行必要的业务处理。这里没有进行任何业务处理。 ```java return queryDao.queryTrain(train); ``` 3,再传递到Dao组件中,在该组件中根据参数对SQL语句和装入到JdbcTemplate中的入参进行拼装,并执行、返回结果。 ```java public List 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 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 list=JdbcTemplate.query(sql, (rs)->{ List 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