1.1 提高程序的安全性。
1.2 将公共的一些属性、方法,封装到一个通用类,这也是封装的提现。
冰箱,彩电,电脑
代码的封装:
将属性设置为私有,然后通过共有的已经设定好的方法暴露给使用者,让使用者按照自己设定好的方式访问该属性,比如性别和年龄
public class Dog {
String name;
private String sex;
private int age;
private double money;
}
测试类代码:
public static void main(String[] args) {
Dog dog=new Dog();
dog.name="旺财";
dog.sex="人妖";
}
public class Cat {
private String name;
private String sex;
private int age;
public void setAge(int age){
if(age>20){
System.out.println("猫咪的年龄超纲了");
}else{
this.age=age;
}
}
public void setSex(String sex){
if(sex.equals("公")||sex.equals("母")) {
this.sex = sex;
}else{
System.out.println("猫咪的性别只能是公母");
}
}
public String getSex(){
return sex;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
}
System.out.println(String);
println()
通过写入行分隔符字符串终止当前行。
void println(boolean x)
打印 boolean 值,然后终止该行。
void println(char x)
打印字符,然后终止该行。
void println(char[] x)
打印字符数组,然后终止该行。
void println(double x)
打印双精度浮点数,然后终止该行。
void println(float x)
打印浮点数,然后终止该行。
void println(int x)
打印整数,然后终止该行。
void println(long x)
打印 long 整数,然后终止该行。
void println(Object x)
打印 Object,然后终止该行。
void println(String x)
打印 String,然后终止该行。
一个类中的同名方法,参数不同:重载
提高的程序复用性,代码的复用。能不能多继承。
类:爹类;娘类;儿子:只能继承一个类;
Dog
public class Dog {
private String name;
private String color;
private String sex;
private int age;
public void eat(){
System.out.println("狗狗"+name+"在吃肉骨头");
}
}
Cat
public class Cat {
private String name;
private String color;
private String sex;
private int age;
public void eat(){
System.out.println("猫咪"+name+"在吃咸鱼");
}
}
java中使用extends来继承父类
public class Pet {
public String name;
private int age;
protected String color;
String sex;
public void eat() {
System.out.println(age+"岁的,"+color+"色的"+sex+name+"在吃");
}
}
子类代码:
public class Cat extends Pet{
public void test(){
this.name;
this.sex;
this.color;
this.age;
}
}
public class Dog extends Pet{
}
父类中有的方法,被子类重写,子类中覆盖注意事项:
方法的可访问行不能比父类差
方法签名必须和父类中的一样
方法不能比父类中抛出更多的异常
public class Pet {
protected String name;
protected int age;
protected String sex;
protected void eat() {
System.out.println(age+"岁的,"+sex+name+"在吃");
}
}
子类中的覆盖:
public class Dog extends Pet{
public void eat(){
System.out.println("狗狗"+name +"在吃肉骨头");
}
}
public class Cat extends Pet{
public void eat(){
super.eat();
System.out.println("猫咪在吃鱼");
}
}
构造方法是不能继承的
子类中的构造方法第一句必须创建父类的对象,即必须创建父类对象后才能创建子类对象。
public class A {
public A() {
System.out.println("构造了A对象");
}
}
public class B extends A{
public B() {
System.out.println("构造了B对象");
}
}
创建子类对象
B b=new B();
输出:
构造了A对象
构造了B对象
继承中的构造方法
1、子类无法继承父类构造方法
2、子类构造方法中第一句一定是调用父类构造方法
3、如果子类没有构造方法,父类必须有无参构造方法,默认构造方法。
4、创建子类对象前,系统需要首先创建父类对象
5、无论是么时候,最好把默认构造方法写上。
equals
源码:
public boolean equals(Object obj) {
return (this == obj);
}
public class Student {
private String name;
private int age;
public boolean equals(Object obj){
if(obj instanceof Student){
Student stu= (Student) obj;
if(stu.age==this.age&&stu.name.equals(this.name)){
return true;
}
}
return false;
}
}
测试类:
public static void main(String[] args) {
Student stu1=new Student("小明",14);
Student stu2=new Student("小明",14);
System.out.println(stu1.equals(stu2));
}
toString:一般情况下,需要子类覆盖
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
hashCode
修饰属性(变量)即为常量,一旦被赋值,就不可改变。
示例:
public final class Person {
String name;
String sex;
int age=19;
static final double classMoney=100;
public Person(String name,String sex,int age) {
this.name=name;
this.sex=sex;
this.age=age;
}
public final void intro() {
System.out.printf("我是%s,在%s班,性别:%s,年龄%d岁,身高%.2f米\n",
name,sex,age);
}
}
测试类
public class StuTest {
public static void main(String[] args) {
}
}
面向对象的三大特征:
封装
继承
多态
编写宠物父类Pet,提供属性:name,age,color,封装年龄age不能超过20岁,带参数的构造方法;方法eat;编写子类Dog,覆盖eat方法;提供子类“看门”guardDoor方法。编写子类Cat,覆盖eat方法;提供子类方法“抓老鼠”catchMouse。编写各自的构造方法,测试运行。
物理世界,水的形态:固态(冰)、液态(水)、气态(水蒸气),静止的。
多态,不仅仅是静止的多种形态,也包括各种不同的形态。
比如,专业来说:针对同样的消息(指令)得到的效果不同;这也是多态;
作用:多态是Java面向对象里面使用非常广泛的一个特性,可以极大的挑高程序的扩展性;
两种形式的多态:
同一类,狗类,闻--》骨头--》吃骨头; 闻--》猫--》抓她。
同一个方法:里面不同的对象,有不同的响应。
三个条件;
1.需要有继承关系,或者子类实现父类接口,实现继承;
2.子类重写父类的方法;
3.父类引用子类的对象;
public class Pet {
protected String name;
protected void eat() {
System.out.println(name+"在吃");
}
}
两个子类代码:
public class Dog extends Pet{
public void eat(){
System.out.println("狗狗"+name +"在吃肉骨头");
}
public void guradDoor(String man){
if(man.equals("生人")){
System.out.println("汪汪");
}else{
System.out.println("摇尾巴");
}
}
public Dog(String name) {
super(name);
}
}
public class Cat extends Pet{
public Cat(String name) {
super(name);
}
public void eat(){
super.eat();
System.out.println("猫咪"+name+"在吃鱼");
}
}
主人类:
public class Master {
String name;
public void feed(Pet pet){
System.out.println("主人"+name+"在喂宠物");
pet.eat();
}
public Master(String name) {
this.name = name;
}
}
测试类:
public static void main(String[] args) {
Pet dog=new Dog("旺财");
Pet cat=new Cat("小强");
Pet rab=new Rabbit("大黑");
Master m=new Master("王海滨");
m.feed(dog);
m.feed(cat);
m.feed(rab);
}
如果要继续饲养更多的宠物,就需要不断地修改Master类中的代码,添加不同宠物的喂养方法。
Pet dog=new Dog("旺财");
Pet cat=new Cat("长江");
dog.guridDoor("生人");//编译错误
向上转型后该对象只能当成父类对象来用,原来子类中定义的属性和方法就被屏蔽掉不能被调用了。比如狗里有一个【看门】的方法,如果向上转型后作为【宠物】类就不能调用【看门】的方法。
向同一个父类的不同子类对象传达同一个消息,行为不同
1、编写父类Pet
public class Pet {
protected String name;
protected void eat() {
SystA em.out.println(name+"在吃");
}
}
2、编写子类
public class Dog extends Pet{
public void eat() {
System.out.println(name+"在吃肉骨头");
}
public Dog(String name) {
this.name=name;
}
}
public class Cat extends Pet{
public Cat(String name) {
this.name=name;
}
public void eat() {
System.out.println(name+"在吃"+"咸鱼干");
}
}
3、编写主类
public class Master {
public String name;
public Master(String name) {
this.name=name;
}
public void feed(Pet pet) {
System.out.println(name+"在喂宠物");
pet.eat();
}
}
4、编写测试类
public static void main(String[] args) {
Master m=new Master("潘旺");
Pet dog=new Dog("旺财");
Pet cat=new Cat("长江");
m.feed(dog);
m.feed(cat);
}
把父类的对象当成子类来用
Pet pet1=new Dog("旺财");
Pet pet2=new Cat("长江");
Dog d=(Dog) pet1;
//Dog e=(Dog) pet2;
Person类,人类;假如就分黑人和白人,new Person(),那这个时候出来的是黑人呢?还是白人?不太清楚。
黑人类,白人类,都可以new一个对象出来。
有时候,一些类不能直接new出来。这个类是一个更为抽象的概念。
Pet:宠物
Animal:抽象概念 --->出来的什么不太清楚???
Dog--->new Dog---》狗
我们在使用子类的时候,子类更为具体,可以直接new出相应的实例。抽象类一般没有对应的实例存在,需要借助于子类来实现。
没有方法体的方法,方法前面需要加abstract,抽象方法必须由子类来具体实现
2.1 有抽象方法的一定是是抽象类,
2.2 抽象类前必须添加abstract;
2.3 抽象类不能被实例化。
2.4 抽象类不一定有抽象方法
子类继承了抽象类,需要实现抽象方法或者也标注成抽象类。
public abstract class Pet {
protected String name;
protected abstract void eat();
}
public class Dog extends Pet{
public Dog(String name) {
this.name=name;
}
protected void eat() {
System.out.println("吃肉骨头");
}
}
主人类及测试类代码
public class Master {
public String name;
public Master(String name) {
this.name=name;
}
public void feed(Pet pet) {
System.out.println(name+"在喂宠物");
pet.eat();
}
}
public static void main(String[] args) {
Master m=new Master("潘旺");
//Pet p=new Pet();//抽象类不能够被实例化
Pet pet1=new Dog("旺财");
Pet pet2=new Cat("长江");
m.feed(pet1);
m.feed(pet2);
}
就是一组规范、规则、模板
接口、类定义的时候,首字母大写,一般这里接口名以I打头。
public interface Work {
public static final int age=9;
public abstract void start();
}
示例:USB接口及实现类
public interface USB {
void work();
}
U盘实现类
public class UDisk implements USB {
@Override
public void work() {
System.out.println("读写文件");
}
}
风扇实现类
public class Fan implements USB {
@Override
public void work() {
System.out.println("吹凉风");
}
}
接口中的变量都是static,final
接口中的方法都是public,abstract
子类实现接口后需要具体实现抽象方法
JDK8提供了default,默认的实现,主要是为了解决超级大接口,都需要实现时太多的无用方法
示例:主人发朋友圈
第一步:定义显示接口
public interface Show {
public void pose() ;
}
第二步:定义Dog实现类
public class Dog implements Show{
@Override
public void pose() {
System.out.println("狗狗"+name+"摆个Pose");
}
}
第三步:定义人实现类
public class Master implements Show {
String name;
public void feed(Pet pet){
System.out.println("主人"+name+"在喂宠物");
pet.eat();
}
public Master(String name) { this.name = name; }
public void showFriend(Show show){
System.out.println("主人"+name+"发朋友圈");
show.pose();
}
@Override
public void pose() {
System.out.println("主人"+name+"好帅");
}
}
第四步:测试类
public static void main(String[] args) {
Master m=new Master("潘旺");
Show dog=new Dog("花花");
m.showFriend(dog);
m.showFriend(m);
}
1、接口不能实例化
2、接口中的所有方法默认都是public abstract;接口中的成员变量:public static final :静态常量
3、接口中不能有具体的方法实现,jdk1.8之后提供了default,允许有默认实现
4、接口中不能有构造方法,静态方法,private
5、非抽象的实现类(子类) 实现接口,必须实现接口中的所有的抽象方法
6、多实现:实现类实现接口,可以实现多个接口:class Sub implements A,B,C
7、接口可以继承接口:A extends B,C
一、编写一个CS游戏:
public interface Weapon {
public void attack();
}
2、AK47和M416实现类
public class AK47 implements Weapon{
String name="AK47";
@Override
public void attack() {
System.out.println("AK47爆头");
}
public String toString() {
return name;
}
}
public class M416 implements Weapon{
String name="M416";
@Override
public void attack() {
System.out.println("M416打敌人1000血");
}
@Override
public String toString() {
return name;
}
}
3、人类
public class Person {
String name;
String sort;
Weapon weap;
public Person(String name,String sort) {
this.name=name;
this.sort=sort;
}
public void setWeapon(Weapon weap) {
this.weap=weap;
System.out.println(sort+name+"已换枪"+weap);
}
public void fight() {
System.out.println(sort+name+"在战斗");
weap.attack();
}
}
4、测试类:
public static void main(String[] args) {
Person p=new Person("杨光磊","警察");
Person c=new Person("赵孔龙","土匪");
AK47 ak=new AK47();
M416 m4=new M416();
p.setWeapon(m4);
c.setWeapon(ak);
p.fight();
c.fight();
M416 mm=new M416();
c.setWeapon(mm);
c.fight();
}
二、主人发朋友圈
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
int jg = num1/num2;
System.out.println(num1+"除以"+num2+"等于"+jg);
}
1、语法结构
try{
}catch(异常类型 异常变量){
处理具体的异常
}finally{
无论如何都要执行的代码
}
2、捕获
3、多重catch
public static void main(String[] args) {
try {
Scanner in = new Scanner(System.in);
System.out.print("请输入被除数:");
int num1 = in.nextInt();
System.out.print("请输入除数:");
int num2 = in.nextInt();
int jg = num1 / num2;
System.out.println(num1 + "除以" + num2 + "等于" + jg);
}catch(ArithmeticException e){
System.out.println("除数不能为零");
System.out.println(e.getMessage());
e.printStackTrace();
}catch(InputMismatchException ex){
System.out.println("请输入数字");
System.out.println(ex.getMessage());
ex.printStackTrace();
}catch(Exception ee){
System.out.println("你出错了");
}finally{
System.out.println("这是无论如何都要执行的finally代码");
}
System.out.println("程序结束");
}
4、finally语句块
public static void main(String[] args){
}
5、自定义异常
a、自定义异常类
public class SexException extends Exception{
public SexException(String msg) {
super(msg);
}
}
b、在Person中设置sex时抛出异常
public class Person {
private String name;
private String sex;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSex() { return sex; }
public void setSex(String sex) throws SexException {
if(sex.equals("男")||sex.equals("女")){
this.sex = sex;
}else{
throw new SexException("性别只能是男女");
}
}
public Person() { }
}
c、测试类代码:
public static void main(String[] args) {
try {
Person p=new Person();
p.setSex("人妖");
p.setName("王海滨");
} catch (SexException e) {
System.out.println(e.getMessage());
}
System.out.println("程序结束");
}
6、抛出异常
7、异常的分类
eclipse中添加jar包到classPath:
1)在项目中新建文件夹【lib】—项目上右键-【Build Path】-【Configure Build path】-在对话框中选中【Libraries】选项-点击【Add JARS】按钮在弹出的【JAR Selection】对话框中选择当前项目中lib目录下的log4j-1.2.9.jar包-点击【确定】关闭【JAR Selection】在【java Build Path页面】单击【Apply and close】
IDEA中添加外部jar包
项目的src文件夹上右键-新建文件夹或包lib
将jar文件拷贝到lib目录中
lib目录上右键-【Add as LIbrary】
1、log4j
public static void main(String[] args) {
Logger logger=Logger.getLogger("exctest");
logger.debug("debug信息");
try {
Scanner in = new Scanner(System.in);
logger.info("info级别");
System.out.print("请输入被除数:");
int num1 = in.nextInt();
logger.warn("warn警告信息");
System.out.print("请输入除数:");
int num2 = in.nextInt();
int jg = num1 / num2;
System.out.println(num1 + "除以" + num2 + "等于" + jg);
}
catch (Exception e) {
logger.error("错误信息");
e.printStackTrace();
}
System.out.println("程序结束");
}
属性文件:
### 把日志信息输出到控制台 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %m%n
### 把日志信息输出到文件:AAA.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=AAA.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
### 设置优先级别、以及输出源 ###
log4j.rootLogger=info,stdout,file
注意:在eclipse中有时候会出现属性文件无法编译输出的情况,这时改动properties文件对日志级别的改动不起作用。可以进入到该项目的硬盘目录中将编译好的log4j.properties文件删除掉,重新运行程序即可。
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
2、日志的信息级别:
Fatal:记录严重的错误,并且会导致应用程序退出
Error:记录严重的错误,但不会影响程序的继续运行
Warn:记录警告
Info:记录程序中比较有意义的信息
Debug:记录程序中的细节信息
java中处理异常的几个关键词是什么?
在使用多个catch块捕获异常时,顺序是什么?
异常的分类有哪些?
1、File类
文件和目录路径名的抽象表示形式
exists(),isFile(),isDirectory(),list(),ListFile(),length(),rename(),getName(),getPath()
示例:显示指定文件夹下直接的文件和文件夹
public static void showFile(String path){
File file=new File(path);//根据路径参数创建File对象
if(!file.exists()||file.isFile()) return;//如果File对象不存在或只是文件则退出
File[] files = file.listFiles();//获得该目录下所有的File对象数组
for(int i=0;i<files.length;i++){//遍历File[]
if(files[i].isDirectory()){//如果当前元素是目录
System.out.println(files[i].getPath()+"\t\t<目录>");//输出该目录的路径
}else{
System.out.println(files[i].getName()+"\t\t"+files[i].length());//如果是文件,则输出文件名和文件大小(单位:字节byte)
}
}
}
测试代码:
public static void main(String[] args) {
showFile("e:/iodemo");
}
对于文件夹目录结构:
只要不断输入下一层文件夹路径,就可以输出该文件夹下的文件和目录
方法递归:
public static void showFile(String path){
File file=new File(path);//根据路径参数创建File对象
if(!file.exists()||file.isFile()) return;//如果File对象不存在或只是文件则退出
File[] files = file.listFiles();//获得该目录下所有的File对象数组
for(int i=0;i<files.length;i++){//遍历File[]
if(files[i].isDirectory()){//如果当前元素是目录
System.out.println(files[i].getPath()+"\t\t<目录>");//输出该目录的路径
showFile(files[i].getPath());//递归调用showFile()继续进行下一级目录的展示
}else{
System.out.println(files[i].getName()+"\t\t"+files[i].length());//如果是文件,则输出文件名和文件大小(单位:字节byte)
}
}
}
1、自定义性别异常要加日志输出
2、列出给定文件夹下所有的路径和文件
生活中的流,水流、电流、人流,流是一组物质从一处通过管道移动到另一处,流具有方向性;
程序中的流是指数据从一处移动到另一处,是一连串不间断的数据集合,即是一连串流动的字节。
功能来分:节点流和处理流
方向来分:输入流和输出流
类型来分:字节流和字符流
观察读取小段文本文件:abcdefghijkm,每次只读取4个字节
public static void main(String[] args) throws Exception{
FileInputStream fis=new FileInputStream("e:/test.txt");
byte[] bs=new byte[4];
int count=fis.read(bs);
System.out.println(new String(bs)+">>>>"+count);
count=fis.read(bs);
System.out.println(new String(bs)+">>>>"+count);
count=fis.read(bs);
System.out.println(new String(bs)+">>>>"+count);
count=fis.read(bs);
System.out.println(new String(bs)+">>>>"+count);
count=fis.read(bs);
System.out.println(new String(bs)+">>>>"+count);
fis.close();
}
观察结果:每次读取4个字节,m是文件结尾,由于只读了一个字母到字节数组中,数组后三个元素没有被新数据所覆盖,仍然保留上一次读取的字母,这样为了正确输出文件内容,可以把new String(bs),改为new String(bs,0,count),并且当读到文件结尾再继续读取时,就会返回-1,可以用这个作为循环读取的条件。
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("e:/aaa.txt");
byte[] bs=new byte[4];
int count;
/* int count=fis.read(bs);
System.out.println(new String(bs)+"---->"+count);
count=fis.read(bs);
System.out.println(new String(bs)+"---->"+count);
count=fis.read(bs);
System.out.println(new String(bs)+"---->"+count);
count=fis.read(bs);
System.out.println(new String(bs)+"---->"+count);
count=fis.read(bs);
System.out.println(new String(bs)+"---->"+count);*/
while((count=fis.read(bs))!=-1){
System.out.println(new String(bs)+"---->"+count);
}
fis.close();
}
加入输出流将文件拷贝到另一个地方
public static void main(String[] args) throws Exception{
}
完整代码:
private static void copyFile(String name1,String name2) throws IOException {
FileInputStream fis = new FileInputStream(name1);
FileOutputStream fos=new FileOutputStream(name2);
byte[] bs=new byte[1024];
int count;
while((count=fis.read(bs))!=-1){
fos.write(bs,0,count);
}
fis.close();
fos.close();
}
由于FileInputStream和OutputStream是节点流,操作的效率很低,需要使用操作流BufferedInputStram和BufferedOutputStream对其进行包装,真实的代码应该修改如下:
public static void main(String[] args) throws Exception{
}
将该操作抽取成方法
private static void copyFile(String name1,String name2) throws IOException {
FileInputStream fis = new FileInputStream(name1);
BufferedInputStream bis=new BufferedInputStream(fis);
FileOutputStream fos=new FileOutputStream(name2);
BufferedOutputStream bos=new BufferedOutputStream(fos);
byte[] bs=new byte[1024];
int count;
while((count=bis.read(bs))!=-1){
bos.write(bs,0,count);
}
bis.close();//先关外层的包装类
bos.close();
fis.close();//再关内层的核心类
fos.close();
}
注意关闭顺序否则会出现以下异常
java.io.IOException: Stream Closed
作业:拷贝文件夹里的所有文件
Reader和Writer
BufferedReader和BufferedWriter
public static void main(String[] args) throws Exception {
FileInputStream fis=new FileInputStream("e:/aaa.txt");
Reader reader=new InputStreamReader(fis);
BufferedReader br=new BufferedReader(reader);
char[] bs=new char[4];
int count=br.read(bs);
System.out.println(new String(bs));
br.close();
reader.close();
fis.close();
FileOutputStream fos=new FileOutputStream("e:/ttt.txt");
Writer writer=new OutputStreamWriter(fos);
BufferedWriter bw=new BufferedWriter(writer);
bw.write("奥斯卡的分水岭的分科撒地方卡士大夫了的课时费");
//bw.flush();//清空缓冲区内容,写到文件中
bw.close();//关闭之前会自动清空缓冲区
writer.close();
fos.close();
}
-Serializable接口和ObjectInputStream类
ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("e:/student.obj");
ObjectOutputStream oos=new ObjectOutputStream(fos);
Student stu1=new Student("张三丰",123);
Student stu2=new Student("张无忌",23);
Student stu3=new Student("张翠山",63);
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.writeObject(stu3);
oos.close();
fos.close();
FileInputStream fis = new FileInputStream("e:/student.obj");
ObjectInputStream ois=new ObjectInputStream(fis);
Student s1= (Student) ois.readObject();
System.out.println(s1);
s1.intro();
Student s2= (Student) ois.readObject();
System.out.println(s2);
s2.intro();
Student s3= (Student) ois.readObject();
System.out.println(s3);
s3.intro();
/* Student s4= (Student) ois.readObject();
System.out.println(s4);*///读到文件结尾后再读会爆EOFException异常
ois.close();
fis.close();
}
如果要存的类没有实现Serializable接口,会爆出下面异常
java.io.NotSerializableException: com.io.Student
Student类代码:
public class Student implements Serializable {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void intro(){
System.out.println("你好我是:"+name+"今年"+age+"岁");
}
...
}
public static void main(String[] args) throws Exception {
PrintWriter pw=new PrintWriter("e:/eeeee.txt");//能自己创建文件
pw.write("案例大富科技绿山咖啡吉林省的反馈");
pw.close();
}
File类
File.separator
流的分类
InputStream和OutputStream
列出指定文件夹下的所有子文件夹和文件;
拷贝文件到另一个文件夹
流的分类?
为什么在流操作时一般不使用FileInputStream和FileOutputStream来直接操作,而要使用包装类?
Collection:List、Set;数组
相同数据类型的集合;问题:长度一般固定的;int[]arr=new int[100];
//实际使用的时候,人数不太确定,人数:20;空间浪费;10000000;
集合:长度不确定;并且集合里面的参数是Object类型。
Map
泛型
Object数组,遍历的速度快,插入和删除的速度慢,是线程不同步的。
public static void main(String[] args) throws Exception {
List list=new ArrayList();
list.add("你好");
list.add(23);
list.add(new Student("李四",88));
list.add(1,new Date());
//list.remove("你好");
list.remove(2);
System.out.println(list.contains("你好"));
//list.clear();
for(Object obj:list){
System.out.println(obj);
}
}
泛型:对于宽泛数据类型的限制;C#2.20 提出,JDK1.5借鉴。
用来界定集合中元素的数据类型,用尖括号表示<>
public static void main(String[] args) {
List<Student> list=new ArrayList<Student>();
}
作业:(15分钟)
拷贝文件
list添加,删除,遍历
list.containes()判断是否包含指定元素,的依据是list中对象的equals方法
链表结构,插入和删除速度快,遍历速度慢
和ArrayList相同,只是线程同步的
和List接口都是Collection的子接口
public static void main(String[] args) throws Exception {
Student stu1=new Student("令狐冲",19);
Student stu2=new Student("令狐冲",19);
Student stu3=new Student("风清扬",79);
Student stu4=new Student("岳不群",49);
HashSet<Student> set=new HashSet<Student>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set.contains(stu2));
for(Student stu:set){
System.out.println(stu);
}
/* Iterator it=set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}*/
}
覆盖Student中的equals和hashCode方法
@Override
public boolean equals(Object obj){
if(obj instanceof Student){
Student stu= (Student) obj;
if(stu.age==this.age&&stu.name.equals(this.name)){
return true;
}
}
return false;
}
@Override
public int hashCode(){
return name.hashCode()+age;
}
再来观察执行结果
true
Student{name='岳不群', age=49}
Student{name='令狐冲', age=19}
Student{name='风清扬', age=79}
排序Comparator和Comparable接口
示例1:Person实现Comparable接口
public class Student implements Comparable<Student>{
...
@Override
public int compareTo(Student stu) {
if(this.age>stu.age) return -1;
if(this.age<stu.age) return 1;
return 0;
}
}
测试类:
public static void main(String[] args) throws Exception {
Student stu1=new Student("令狐冲",19);
Student stu2=new Student("令狐冲",19);
Student stu3=new Student("风清扬",79);
Student stu4=new Student("岳不群",49);
TreeSet<Student> set= new TreeSet<Student>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set.contains(stu2));
for(Student stu:set){
System.out.println(stu);
}
/* Iterator it=set.iterator();
想一想:result.next
while(it.hasNext()){
System.out.println(it.next());
}*/
}
输出就是按照年龄的顺序来输出的
示例2:创建实现Comparator接口的比较器
public class StuComptor implements Comparator<Student> {
@Override
public int compare(Student stu1, Student stu2) {
if(stu1.age>stu2.age)return 1;
if(stu1.age<stu2.age)return -1;
return 0;
}
}
Person类可以不必实现Comparable接口,保持原有Person的POJO特性,利用比较器来完成排序
测试类代码:
public static void main(String[] args) throws Exception {
Student stu1=new Student("令狐冲",19);
Student stu2=new Student("令狐冲",19);
Student stu3=new Student("风清扬",79);
Student stu4=new Student("岳不群",49);
TreeSet<Student> set= new TreeSet<Student>(new StuComptor());
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set.contains(stu2));
for(Student stu:set){
System.out.println(stu);
}
/* Iterator it=set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}*/
}
3、LinkedHashSet
public static void main(String[] args) throws Exception {
Student stu1=new Student("令狐冲",19);
Student stu2=new Student("令狐冲",19);
Student stu3=new Student("风清扬",79);
Student stu4=new Student("岳不群",49);
LinkedHashSet<Student> set= new LinkedHashSet<Student>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set.contains(stu2));
for(Student stu:set){
System.out.println(stu);
}
/* Iterator it=set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}*/
}
按照加入的顺序排列
true
Student{name='令狐冲', age=19}
Student{name='风清扬', age=79}
Student{name='岳不群', age=49}
线程不同步,键和值都可以为null;
public static void main(String[] args) {
HashMap map=new HashMap(111,0.9f);
map.put("one","111111");
map.put("two","222222");
map.put("three",null);
map.put(null,"999999");
map.put(null,"000000");
map.put("four","444444");
map.put("five","555555");
map.remove("two");
System.out.println(map.containsKey("five"));
Set<Map.Entry> enset=map.entrySet();
for(Map.Entry en:enset){
System.out.println(en);
}
Set keySet=map.keySet();
for (Object key:keySet){
System.out.println(key+"--->"+map.get(key));
}
}
线程同步,锁定所有数据,键和值都不能为null;
public static void main(String args[]) throws Exception {
}
线程同步,只锁定部分数据
1、示例:
要查找一个数(取值范围为1-100)是否包含在集合[4,7,11,21,8,14,17]中,应该怎么办。
private static boolean hashFind(int num) {
int[] arr={4,7,11,21,8,14,17,34};
for(int i=0;i<arr.length;i++){
if(arr[i]==num){
return true;
}
}
return false;
}
如果使用长度是100的数组
让集合中数值对应数组下标的元素赋值为:1
2、当取值范围无限扩大后
使用hash函数确定某个数应该的位置
public static void main(String args[]) throws Exception {
TreeSet<Person> set=new TreeSet<Person>();
set.add(new Person("张三",23));
set.add(new Person("李四",3));
set.add(new Person("王麻子",7));
set.add(new Person("找刘龙",58));
Map<String,Person> map=new HashMap<String, Person>();
ArrayList<Person> list=new ArrayList<Person>();
for(Person p:set) {
System.out.println(p);
map.put(p.getName(), p);
list.add(p);
}
for(Object key:map.keySet()) {
System.out.println(key+">>"+map.get(key));
}
for(Person p:list) {
System.out.println(p);
}
}
DriverManager:驱动管理器
Connection:数据库连接
Statement:sql语句
ResultSet:返回结果集
JDBC驱动程序管理器:是JDBC的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在数据库和相应的驱动程序之间建立连接。 JDBC标准规定:所有的驱动程序类必须包含一个静态部分。这个静态部分在加载该实例时由DriverManager类进行注册。 用户在正常情况下将不会直接调用DriverManager.regiserDriver方法,而是在加载驱动程序时由驱动程序自动调用。 注册驱动程序:
Class.forName("com.mysql.cj.jdbc.Driver");
Class.forName("com.microsoft.sqlserver.jdbc. SQLServerDriver");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Class.forName( "oracle.jdbc.driver.OracleDriver ");
注册的驱动程序类名称必须在用户的classPath中。
static Connection getConnection(String url,String user,String password):
url: jdbc:<subprotocol>:<subname>
协议: jdbc表示协议,它是唯一的,jdbc只有这一个协议。
子协议: 主要用于识别数据库驱动程序,(不同的数据库驱动程序不同。)
子名: 属于专门的驱动程序。数据源名。
数据源名。
jdbc:odbc:news//ODBC桥接方式的URL
jdbc:sqlserver://localhost:1433;DatabaseName=news//SQLServer的URL
jdbc:oracle:thin:@localhost:1521:orcl //oracle的URL
jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai
1、数据库连接及增删改操作——纯粹代码
//1.注册驱动
//2.获得连接对象
//3、获得语句对象
//4、执行sql语句
//5、关闭数据库连接
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获得连接对象
String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
Connection con=DriverManager.getConnection(url,"root","admin");
//3、获得语句对象
Statement st=con.createStatement();
//4、执行sql语句
String sql="update bank set balance=90000 where id=6";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("数据库操作成功");
}
//5、关闭数据库连接
st.close();
con.close();
}
2、增删改操作——添加异常处理
public static void main(String[] args) {
Connection con= null;
Statement st= null;
try {
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获得连接对象
String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
con = DriverManager.getConnection(url,"root","admin");
//3、获得语句对象
st = con.createStatement();
//4、执行sql语句
String sql="update bank set balance=90000 where id=6";
int i = st.executeUpdate(sql);
if(i>0){
System.out.println("数据库操作成功");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {//5、关闭数据库连接
st.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
如果录入或修改有中文,则有的版本会出现中文乱码问题
可以在url后面加上:useUnicode=true&characterEncoding=UTF-8
1、结果集合ResultSet
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获得连接对象
String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
Connection con=DriverManager.getConnection(url,"root","admin");
//3、获得语句对象
Statement st=con.createStatement();
//4、执行sql语句
String sql="select * from bank";
ResultSet resultSet = st.executeQuery(sql);
while(resultSet.next()){
System.out.print(resultSet.getString(1)+"\t");
System.out.print(resultSet.getString("account")+"\t");
System.out.println(resultSet.getString(3)+"\t");
}
//5、关闭数据库连接
resultSet.close();
st.close();
con.close();
}
错误:
java.sql.SQLException: No suitable driver found for jdbc:mysql//localhost:3306/test?serverTimezone=Asia/Shanghai
URL写错了
2、查询结果封装成对象并装载集合
package com.jdbc;
public class Bank {
private int id;
private String account;
private double balance;
@Override
public String toString() {
return "Bank{" +
"id=" + id +
", account='" + account + '\'' +
", balance=" + balance +
'}';
}
public Bank(int id, String account, double balance) {
this.id = id;
this.account = account;
this.balance = balance;
}
public Bank() {
}
...
}
查询代码:
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获得连接对象
String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
Connection con=DriverManager.getConnection(url,"root","admin");
//3、获得语句对象
Statement st=con.createStatement();
//4、执行sql语句
String sql="select * from bank";
ResultSet resultSet = st.executeQuery(sql);
List<Bank> list=new ArrayList<Bank>();
//5、处理结果集
while(resultSet.next()){
Bank bank=new Bank(resultSet.getInt(1),
resultSet.getString(2),
resultSet.getDouble(3));
list.add(bank);
}
///6、关闭数据库连接
resultSet.close();
st.close();
con.close();
for(Bank b:list){
System.out.println(b);
}
}
DriverManager
Connection
Statement
ResultSet
1、注册驱动
2、获得连接
3、获得语句
4、执行语句
5、处理结果集(查询需要)
6、关闭各种接口对象
字段名 | 字段类型 | 备注 |
---|---|---|
shopId | int | 商品编号;主键、自增 |
shopName | varchar | 商品名称 |
shopPrice | double | 商品价格 |
addDate | date | 生产日期 |
1、参数设置
package com.jdbc;
import java.sql.*;
import java.time.LocalDate;
/**
* @author: wangxiangnan
* @time: 2020/8/7 11:06
* @description:
*/
public class JDBCMain {
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
Connection con=DriverManager.getConnection(url,"root","admin");
String sql="insert into dept values(null,?,?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1,"医学部3");
//ps.setDate(2,java.sql.Date.valueOf("2001-12-16"));
ps.setObject(2, LocalDate.now());
ps.setObject(2,new java.util.Date());
int count=ps.executeUpdate();
if(count>0){
System.out.println("录入成功");
}else{
System.out.println("录入失败");
}
ps.close();
con.close();
}
}
2、java.util.Date 和java.sql.Date以及Timestamp
public static void main(String[] args) {
}
Wed Jun 19 15:32:38 CST 2019
2019-06-19
2019-06-19 15:32:38.111
3、SQL注入攻击
String sql="select * from users where username=' ' and pass=' '";
String sql="select * from users where username='' or '0'='0' and pass='' or '0'='0'";
' or '0'='0 ;
' or '0'='0
4、抽取设置参数的通用方法
public static void setParams(PreparedStatement ps,Object[] params) throws SQLException { if(params==null)return;
for(int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);
}
}
#设置参数常见的错误
Exception in thread "main" java.sql.SQLException: Parameter index out of range (5 > number of parameters, which is 4). --?少参数多
java.sql.SQLException: No value specified for parameter 6 ##?多参数少
测试
public static void main(String[] args) throws Exception{
//1.注册驱动
//2.获得连接
//3、获得语句对象
//4、执行语句
//调用通用的设置参数方法
//5、关闭数据库连接
}
public class MyDB {
public static String driver="com.mysql.cj.jdbc.Driver";
public static String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
public static String user="root";
public static String pass="admin";
static{
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConn() throws SQLException {
return DriverManager.getConnection(url,user,pass);
}
public static int update(String sql,Object[] params) throws SQLException {
Connection con = null;
PreparedStatement ps = null;
try {
con = getConn();
ps = con.prepareStatement(sql);
setParams(ps,params);
return ps.executeUpdate();
} finally {
closeAll(null,ps,con);
}
}
public static void setParams(PreparedStatement ps,Object[] params) throws SQLException {
if(params!=null){
for(int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);
}
}
}
public static void closeAll(ResultSet rs, Statement st, Connection con){
if(rs!=null){
try {
rs.close();
rs=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
st=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
con=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
测试代码:
public static void main(String[] args) {
String sql="insert into classes(className,createDate) values(?,?)";
BaseDB.update(sql, new Object[] {"A888",new Date()});
}
要编写通用查询就要知道传进来的SQL语句的结果集有多少字段:
元数据:
结果集的媒体元数据,可以获得结果集的底层数据库相关信息。
package java.sql;
public interface ResultSetMetaData extends Wrapper {
int getColumnCount() throws SQLException;//获得列数
boolean isAutoIncrement(int column) throws SQLException;
boolean isCaseSensitive(int column) throws SQLException;
boolean isSearchable(int column) throws SQLException;
boolean isCurrency(int column) throws SQLException;
int isNullable(int column) throws SQLException;
int columnNoNulls = 0;
int columnNullable = 1;
int columnNullableUnknown = 2;
boolean isSigned(int column) throws SQLException;
int getColumnDisplaySize(int column) throws SQLException;
String getColumnLabel(int column) throws SQLException;//获得字段别名
String getColumnName(int column) throws SQLException;//获得字段名
String getSchemaName(int column) throws SQLException;
int getPrecision(int column) throws SQLException;
int getScale(int column) throws SQLException;
String getTableName(int column) throws SQLException;
String getCatalogName(int column) throws SQLException;
int getColumnType(int column) throws SQLException;
String getColumnTypeName(int column) throws SQLException;
boolean isReadOnly(int column) throws SQLException;
boolean isWritable(int column) throws SQLException;
boolean isDefinitelyWritable(int column) throws SQLException;
//--------------------------JDBC 2.0-----------------------------------
String getColumnClassName(int column) throws SQLException;
}
public static List<List> query(String sql, Object[] params) throws SQLException {
Connection con=null;
List<List> tabList;//返回查询结果的表List
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = getConn();
tabList = new ArrayList();//创建表List
ps = con.prepareStatement(sql);
setParams(ps,params);
rs = ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();//获得结果集的媒体元数据
int count=rsmd.getColumnCount();//获得结果集的列数
while(rs.next()){
List rowList=new ArrayList();//创建行的集合
for(int i=1;i<=count;i++){
rowList.add(rs.getObject(i));//将行中每列的数据加入到rowList中
}
tabList.add(rowList);//将加完数据的rowList加入到tabList中
}
} finally {
closeAll(rs,ps,con);
}
return tabList;//返回tabList
}
public static List<Map> queryMap(String sql, Object[] params) throws SQLException {
Connection con=null;
List<Map> tabList;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = getConn();
tabList = new ArrayList();
ps = con.prepareStatement(sql);
setParams(ps,params);
rs = ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
while(rs.next()){
//List rowList=new ArrayList();
Map rowMap=new HashMap();
for(int i=1;i<=count;i++){
rowMap.put(rsmd.getColumnName(i),rs.getObject(i));
}
tabList.add(rowMap);
}
} finally {
closeAll(rs,ps,con);
}
return tabList;
}
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
数据库服务未启动
java.sql.SQLException: No suitable driver found for jdbc:mysql//localhost:3306/school?serverTimezone=UTC
URL错误
java.sql.SQLSyntaxErrorException: Unknown database 'schoo'
未知的数据库“schoo”
java.sql.SQLException: The server time zone value '???ú±ê×??±??' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
serverTimezone=UTC 写错
java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
数据库密码错误
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'selec * from classes' at line 1
SQL语句错误,要招关键词:near ,就在near的后面出的错
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
java.sql.SQLSyntaxErrorException: Table 'school.classs' doesn't exist
数据库表“school.classs ”不存在
java.sql.SQLException: No value specified for parameter 1
sql语句中的第一个参数没有给定参数,一般是没有设置参数
SQLIntegrityConstraintViolationException: Duplicate entry '654321' for key 'order_no'
违反了唯一约束
public class BaseDB {
public static String driver="com.mysql.cj.jdbc.Driver";
public static String url="jdbc:mysql://localhost:3306/school?serverTimezone=UTC";
public static String user="root";
public static String pass="admin";
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static List<Map> queryMap(String sql,Object[] params){
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
List list=new ArrayList();
try {
con = getConnection();
ps = con.prepareStatement(sql);
setParam(ps,params);
rs = ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
while(rs.next()) {
Map map=new LinkedHashMap();
for(int i=1;i<=count;i++) {
map.put(rsmd.getColumnName(i), rs.getObject(i));
//System.out.print(rs.getObject(i)+"\t");
}
list.add(map);
//System.out.println();
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
closeAll(rs,ps,con);
}
return list;
}
public static List<List> queryList(String sql,Object[] params){
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
List tabList=new ArrayList();
try {
con = getConnection();
ps = con.prepareStatement(sql);
setParam(ps,params);
rs = ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
while(rs.next()) {
List rowList=new ArrayList();
for(int i=1;i<=count;i++) {
rowList.add(rs.getObject(i));
}
tabList.add(rowList);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
closeAll(rs,ps,con);
}
return tabList;
}
public static int update(String sql,Object[] params) {
Connection con = null;
PreparedStatement ps = null;
try {
con = getConnection();
ps = con.prepareStatement(sql);
setParam(ps,params);
return ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
closeAll(null,ps,con);
}
return -1;
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, pass);
}
public static void setParam(PreparedStatement ps,Object[] params) throws SQLException {
if(params!=null) {
for(int i=0;i<params.length;i++) {
ps.setObject(i+1, params[i]);
}
}
}
public static void closeAll(ResultSet rs,Statement st,Connection con) {
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
0)编写BaseDB。。。
public interface DeptDao {
int addDept(Dept dept);
int updateDept(Dept dept);
int deleteDept(int deptno);
Dept findDeptById(int deptno);
List<Dept> findAllDept();
List<Dept> dindDeptByName(String name);
}
public class Dept {
private int deptno;
private String dname;
private java.sql.Date createTime;
...
}
package com.jdbc;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author: wangxiangnan
* @time: 2020/8/11 15:38
* @description:
*/
public class DeptDaoImpl implements DeptDao {
@Override
public int addDept(Dept dept) {
return 0;
}
@Override
public int updateDept(Dept dept) {
return 0;
}
@Override
public int deleteDept(int deptno) {
return 0;
}
@Override
public Dept findDeptById(int deptno) {
List<Map> list= null;
try {
list = MyDB.queryMap("select * from dept where deptno=?",new Object[]{deptno});
} catch (SQLException e) {
e.printStackTrace();
}
if(list.size()>0){
Map map=list.get(0);
Dept dept=new Dept((Integer)map.get("deptno"),
(String)map.get("dname"),
(java.sql.Date)map.get("createTime"));
return dept;
}
return null;
}
@Override
public List<Dept> findAllDept() {
List<List> dlist= null;
try {
dlist = MyDB.query("select deptno,dname,createTime from dept",null);
} catch (SQLException e) {
e.printStackTrace();
}
List<Dept> deptList=new ArrayList();
for(List row:dlist){
Dept dept=new Dept((Integer)row.get(0),(String)row.get(1),(java.sql.Date)row.get(2));
deptList.add(dept);
}
return deptList;
}
@Override
public List<Dept> dindDeptByName(String name) {
return null;
}
}
public static void main(String[] args) throws Exception {
DeptDao dao=new DeptDaoImpl();
Dept dept=dao.findDeptById(2);
System.out.println(dept);
List<Dept> all=dao.findAllDept();
System.out.println(all);
}
如果遇到数据库中的decimal类型字段,只能转换成BigDecimal类型:如果实体类的属性是double类型的,需要如下转换:
((BigDecimal)row.get(1)).doubleValue()
DAO实现类中,只要是查询就要用到将tabList中Map或List转换为实体的操作,出现大量重复代码,现在将它提取出来,供所有查询方法调用。
private Dept transEntity(Map deptMap){
if(deptMap.size()>0)
return new Dept((Integer)deptMap.get("deptno"),
(String)deptMap.get("dname"),
(Date) deptMap.get("createTime"));
return null;
}
参数数组使用起来有些麻烦,可以使用不定参数
不定参数的实质也是一个数组,可以将参数当成数组处理。
package com.jdbc;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author: wangxiangnan
* @time: 2020/8/10 15:47
* @description:
*/
public class MyDB {
public static String driver="com.mysql.cj.jdbc.Driver";
public static String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
public static String user="root";
public static String pass="admin";
static{
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConn() throws SQLException {
return DriverManager.getConnection(url,user,pass);
}
public static List<Map> queryMap(String sql, Object... params) throws SQLException {
Connection con=null;
List<Map> tabList;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = getConn();
tabList = new ArrayList();
ps = con.prepareStatement(sql);
setParams(ps,params);
rs = ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
while(rs.next()){
//List rowList=new ArrayList();
Map rowMap=new HashMap();
for(int i=1;i<=count;i++){
rowMap.put(rsmd.getColumnName(i),rs.getObject(i));
}
tabList.add(rowMap);
}
} finally {
closeAll(rs,ps,con);
}
return tabList;
}
public static List<List> query(String sql, Object... params) throws SQLException {
Connection con=null;
List<List> tabList;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = getConn();
tabList = new ArrayList();
ps = con.prepareStatement(sql);
setParams(ps,params);
rs = ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
while(rs.next()){
List rowList=new ArrayList();
for(int i=1;i<=count;i++){
rowList.add(rs.getObject(i));
}
tabList.add(rowList);
}
} finally {
closeAll(rs,ps,con);
}
return tabList;
}
public static int update(String sql,Object... params) throws SQLException {
Connection con = null;
PreparedStatement ps = null;
try {
con = getConn();
ps = con.prepareStatement(sql);
setParams(ps,params);
return ps.executeUpdate();
} finally {
closeAll(null,ps,con);
}
}
public static void setParams(PreparedStatement ps,Object... params) throws SQLException {
if(params!=null){
for(int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);
}
}
}
public static void closeAll(ResultSet rs, Statement st, Connection con){
if(rs!=null){
try {
rs.close();
rs=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
st=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
con=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
这样在具体调用的时候就可以直接使用单个参数了
@Override
public int updateDept(Dept dept) throws SQLException {
String sql="update dept set dname=?,createTime=? where deptno=?";
return MyDB.update(sql,dept.getDname(),dept.getCreateTime(),dept.getDeptno());
}
在自动增长主键的表中插入一条数据,往往需要获得该数据的主键。
public static int insertGetKey(String sql,Object[] params) throws SQLException {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con=getConn();
ps = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
setParams(ps,params);
int count = ps.executeUpdate();
rs=ps.getGeneratedKeys();
if(rs.next()){
return rs.getInt(1);
}
}finally{
closeAll(rs,ps,con);
}
return -1;
}
所有通用的代码:
package com.jdbc;
public class BaseDB {
public static String driver="com.mysql.cj.jdbc.Driver";
public static String url="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai";
public static String user="root";
public static String pass="admin";
static{
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConn() throws SQLException {
return DriverManager.getConnection(url,user,pass);
}
public static List<Map> queryMap(String sql, Object... params) throws SQLException {
Connection con=null;
List<Map> tabList;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = getConn();
tabList = new ArrayList();
ps = con.prepareStatement(sql);
setParams(ps,params);
rs = ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
while(rs.next()){
//List rowList=new ArrayList();在这基础上修改
Map rowMap=new HashMap();
for(int i=1;i<=count;i++){
rowMap.put(rsmd.getColumnName(i),rs.getObject(i));
}
tabList.add(rowMap);
}
} finally {
closeAll(rs,ps,con);
}
return tabList;
}
public static List<List> query(String sql, Object... params) throws SQLException {
Connection con=null;
List<List> tabList;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = getConn();
tabList = new ArrayList();
ps = con.prepareStatement(sql);
setParams(ps,params);
rs = ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
while(rs.next()){
List rowList=new ArrayList();
for(int i=1;i<=count;i++){
rowList.add(rs.getObject(i));
}
tabList.add(rowList);
}
} finally {
closeAll(rs,ps,con);
}
return tabList;
}
public static int update(String sql,Object... params) throws SQLException {
Connection con = null;
PreparedStatement ps = null;
try {
con = getConn();
ps = con.prepareStatement(sql);
setParams(ps,params);
return ps.executeUpdate();
} finally {
closeAll(null,ps,con);
}
}
public static void setParams(PreparedStatement ps,Object... params) throws SQLException {
if(params!=null){
for(int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);//不定参数也是数组
}
}
}
public static void closeAll(ResultSet rs, Statement st, Connection con){
if(rs!=null){
try {
rs.close();
rs=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
st=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
con=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
测试类代码:
public class OrderMain {
public static void main(String[] args) throws SQLException {
String sql="insert into orders values(null,?,?,?)";
int orderid=MyDB.insertGetKey(sql,"202008131235","京东平台", Date.valueOf("2020-08-11"));
System.out.println(orderid);
List<Object[]> plist=new ArrayList();//相当于外面传过来的参数
plist.add(new Object[]{orderid,"华为手机",200,4567.0});
plist.add(new Object[]{orderid,"小米手机",100,2567.0});
plist.add(new Object[]{orderid,"苹果手机",300,6567.0});
plist.add(new Object[]{orderid,"OPPO手机",500,3567.0});
sql="insert into order_detail values(null,?,?,?,?)";
for(Object[] params:plist){
MyDB.update(sql,params);
}
}
}
Orders:
public class Orders {
private int orderId;
private String orderNO;
private String customer;
private Date orderDate;
...
}
OrderDetail
public class OrderDetail {
private int detailId;
private int orderId;
private String goodsName;
private int count;
private double price;
...
}
OrderDao
public interface OrderDao {
int addOrder(Orders order);
List<Orders> findAllOrder();
}
OrderDaoImpl
public class OrdersDaoImpl implements OrderDao {
@Override
public int addOrder(Orders order) {
String sql="insert into orders values(null,?,?,?)";
return 0;
}
@Override
public List<Orders> findAllOrder() {
return null;
}
}
OrderDetailDao
public interface OrderDetailDao {
int addOrderDetail(OrderDetail od);
List<OrderDetail> findAllOrderDetail();
}
OrderDetailDaoImpl
public class OrderDetailImpl implements OrderDetailDao {
@Override
public int addOrderDetail(OrderDetail od) {
String sql="insert into order_detail values(null,?,?,?,?)";
return 0;
}
@Override
public List<OrderDetail> findAllOrderDetail() {
return null;
}
}
测试类
public class JDBCMain {
public static void main(String[] args) throws Exception {
OrderDao od=new OrdersDaoImpl();
OrderDetailDao odd=new OrderDetailImpl();
int orderid=od.addOrder(new Orders("654321","淘宝商家1",Date.valueOf("2020-11-25")));
List<Object[]> plist=new ArrayList();
plist.add(new Object[]{orderid,"华为手机",200,4567.0});
plist.add(new Object[]{orderid,"小米手机",100,2567.0});
plist.add(new Object[]{orderid,"苹果手机",300,6567.0});
plist.add(new Object[]{orderid,"OPPO手机",500,3567.0});
for(Object[] params:plist){
odd.addOrderDetail(
new OrderDetail((Integer)params[0],
(String)params[1],
(Integer)params[2],
(Double)params[3]));
}
System.out.println(od.findAllOrder());
System.out.println(odd.findAllOrderDetail());
}
在自动提交模式下,每个SQL更新语句(insert,update,delete)成功执行完后就会自动提交到数据库中。
为了将多个数据库更新组合成一组更新,我们需要将自动提交模式关闭(使用setAutoCommit(boolean auto)方法)。
一旦关闭了自动提交模式,每个SQL语句都是一个事务的一部分,为使事务对数据库产生永久效果,需要使用 commit()方法来显式地进行提交。
在自动提交关闭后,不成功的提交会导致数据库进行隐式的回滚,所有的更新都会丢失。
也可以调用rollback();
public void trans(){
Connection con=null;
PreparedStatement pstmt=null;
try {
con=getConnection();
//con.setAutoCommit(false);
String sql1="insert into student values(?,?,?)";
pstmt=con.prepareStatement(sql1);
pstmt.setString(1,"孙悟空");
pstmt.setString(2, "男");
pstmt.setDate(3, java.sql.Date.valueOf("1953-5-13"));
pstmt.executeUpdate();
System.out.println("第一次录入成功");
pstmt.setString(1,"观世音");
pstmt.setString(2, "女");
pstmt.setDate(3, java.sql.Date.valueOf("175300-5-13"));
pstmt.executeUpdate();
System.out.println("第二次录入成功");
//con.commit();
} catch (SQLException e) {
//con.rollback();
}
}
private static void batchExecute() throws SQLException {
long starttime=System.currentTimeMillis();
System.out.println("开始:"+starttime);
Connection con= BaseDB.getConnection(false);
String sql="insert tb_test values(null,?,?,?)";
PreparedStatement ps=con.prepareStatement(sql);
for(int i=0;i<100006;i++){
BaseDB.setParams(ps,new Object[]{"李"+i,i%100,Math.random()*100});
ps.addBatch();
if(i%1000==0){
ps.executeBatch();
ps.clearBatch();
System.out.println(System.currentTimeMillis());
}
}
ps.executeBatch();
BaseDB.closeAll(null,ps,con);
long endtime=System.currentTimeMillis();
System.out.println("结束"+endtime);
System.out.println("程序花费时间:" + (endtime-starttime)/1000 + "秒!!");
}
public static void main(String[] args) throws Exception{
//1.注册驱动
String driver="com.mysql.cj.jdbc.Driver";
String url="jdbc:mysql://127.0.0.1:3306/school?serverTimezone=UTC";
//2.获得连接
//3、获得语句对象
Class.forName(driver);
Connection con = DriverManager.getConnection(url, "root", "admin");
//4、执行语句
String cla="A777";
java.util.Date date=new java.util.Date();
String sql="insert into classes(className,createDate) values(?,?)";
PreparedStatement st = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
setParam(st,new Object[] {cla,date});
int count=st.executeUpdate();
ResultSet rs=st.getGeneratedKeys();
if(rs.next()) {
int key=rs.getInt(1);
System.out.println("主键:"+key);
}
st.close();
con.close();
}
public static int insertGetKey(String sql,Object[] params) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConnection();
pstmt = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
setParam(pstmt,params);
pstmt.executeUpdate();
ResultSet rs=pstmt.getGeneratedKeys();
if(rs.next()) {
System.out.println("主键:"+rs.getInt(1));
return rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll(null,pstmt,con);
}
return -1;
}
数据库表格:
-- ----------------------------
-- Table structure for `orders`
-- ----------------------------
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`orderId` int(11) NOT NULL AUTO_INCREMENT,
`orderDate` date DEFAULT NULL,
`orderAddress` varchar(50) DEFAULT NULL,
PRIMARY KEY (`orderId`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
CREATE TABLE `orderdetail` (
`detailId` int(11) NOT NULL AUTO_INCREMENT,
`shopName` varchar(20) DEFAULT NULL,
`shopPrice` double DEFAULT NULL,
`shopCount` double DEFAULT NULL,
`fk_orderId` int(11) DEFAULT NULL,
PRIMARY KEY (`detailId`),
KEY `fk_orderId` (`fk_orderId`),
CONSTRAINT `orderdetail_ibfk_1` FOREIGN KEY (`fk_orderId`) REFERENCES `orders` (`orderid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
public static void main(String[] args) {
String sql="insert into orders values(null,?,?)";
int key=BaseDB.insertGetKey(sql, new Object[] { new Date(),"AAA软件学院4号楼"});
sql="insert into orderdetail values(null,?,?,?,?)";
BaseDB.update(sql, new Object[] {"华为9001",8900.8,3,key});
BaseDB.update(sql, new Object[] {"小米8848",1900.8,2,key});
System.out.println("key===="+key);
}
public static void main(String[] args){
//1.注册驱动
String driver="com.mysql.cj.jdbc.Driver";
String url="jdbc:mysql://127.0.0.1:3306/school?serverTimezone=UTC";
//2.获得连接
//3、获得语句对象
Connection con = null;
PreparedStatement st = null;
try {
Class.forName(driver);
con = DriverManager.getConnection(url, "root", "admin");
//4、执行语句
con.setAutoCommit(false);//设置自动提交模式为false
java.util.Date date=new java.util.Date();
String sql="insert into classes(className,createDate) values(?,?)";
st = con.prepareStatement(sql);
setParam(st,new Object[] {"A000",date});
st.executeUpdate();
setParam(st,new Object[] {"A009",date});
st.executeUpdate();
setParam(st,new Object[] {"A9900","2019-5-12"});
st.executeUpdate();
con.commit();//提交数据库操作
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
try {
con.rollback();//如果出错则回滚事务
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
st.close();
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1、数据库表结构
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `board`
-- ----------------------------
DROP TABLE IF EXISTS `board`;
CREATE TABLE `board` (
`bid` int(11) NOT NULL AUTO_INCREMENT,
`bname` varchar(50) NOT NULL,
`state` int(11) DEFAULT NULL,
PRIMARY KEY (`bid`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of board
-- ----------------------------
INSERT INTO `board` VALUES ('1', 'Python板块', '1');
INSERT INTO `board` VALUES ('2', 'java板块', '1');
INSERT INTO `board` VALUES ('3', 'C#板块', '1');
-- ----------------------------
-- Table structure for `reply`
-- ----------------------------
DROP TABLE IF EXISTS `reply`;
CREATE TABLE `reply` (
`rid` int(11) NOT NULL AUTO_INCREMENT,
`context` varchar(1000) NOT NULL,
`ptime` datetime NOT NULL,
`fk_uid` int(11) NOT NULL,
`fk_tid` int(11) NOT NULL,
PRIMARY KEY (`rid`),
KEY `fk_uid` (`fk_uid`),
KEY `fk_tid` (`fk_tid`),
CONSTRAINT `reply_ibfk_1` FOREIGN KEY (`fk_uid`) REFERENCES `userinfo` (`uid`),
CONSTRAINT `reply_ibfk_2` FOREIGN KEY (`fk_tid`) REFERENCES `topic` (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of reply
-- ----------------------------
INSERT INTO `reply` VALUES ('2', '这才是微软的救星啊', '2019-06-24 03:19:24', '2', '7');
INSERT INTO `reply` VALUES ('3', '从入门到放弃', '2019-06-24 03:45:06', '2', '4');
INSERT INTO `reply` VALUES ('4', '你净瞎说', '2019-06-24 03:59:54', '2', '4');
INSERT INTO `reply` VALUES ('5', '能精通么?', '2019-06-24 04:00:18', '2', '4');
-- ----------------------------
-- Table structure for `topic`
-- ----------------------------
DROP TABLE IF EXISTS `topic`;
CREATE TABLE `topic` (
`tid` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(30) NOT NULL,
`context` varchar(1000) NOT NULL,
`ptime` datetime NOT NULL,
`fk_uid` int(11) NOT NULL,
`fk_bid` int(11) NOT NULL,
PRIMARY KEY (`tid`),
KEY `fk_uid` (`fk_uid`),
KEY `fk_bid` (`fk_bid`),
CONSTRAINT `topic_ibfk_1` FOREIGN KEY (`fk_uid`) REFERENCES `userinfo` (`uid`),
CONSTRAINT `topic_ibfk_2` FOREIGN KEY (`fk_bid`) REFERENCES `board` (`bid`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of topic
-- ----------------------------
INSERT INTO `topic` VALUES ('3', 'Python入门', '人生苦短、我用Python', '2019-06-20 08:24:07', '3', '1');
INSERT INTO `topic` VALUES ('4', 'java从入门到精通', '这是一个永恒的话题', '2019-06-24 02:37:16', '2', '2');
INSERT INTO `topic` VALUES ('5', 'java框架技术', 'spring+Mybatis项目整合', '2019-06-24 02:43:13', '2', '2');
INSERT INTO `topic` VALUES ('6', 'Python的发展', '自从1994年那个漆黑的夜晚,一个荷兰人开启了无聊模式', '2019-06-24 02:52:26', '2', '1');
INSERT INTO `topic` VALUES ('7', 'C#由来', 'Delphi的设计师主持了C#的编写', '2019-06-24 02:53:40', '2', '3');
INSERT INTO `topic` VALUES ('8', 'JDBC入门', 'JDBC的API简介:DriverManager;Connection', '2019-06-24 04:35:10', '2', '2');
INSERT INTO `topic` VALUES ('9', '蟒蛇的前世今生', '杭州有个西湖,镇江有个金山寺,两者什么关系呢,这得从白蛇说起', '2019-06-24 04:39:45', '2', '1');
-- ----------------------------
-- Table structure for `userinfo`
-- ----------------------------
DROP TABLE IF EXISTS `userinfo`;
CREATE TABLE `userinfo` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`uname` varchar(20) NOT NULL,
`upass` varchar(10) NOT NULL,
`state` int(11) NOT NULL,
`flag` int(11) NOT NULL,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of userinfo
-- ----------------------------
INSERT INTO `userinfo` VALUES ('1', '西门庆', '1234', '0', '0');
INSERT INTO `userinfo` VALUES ('2', '武大郎', '1234', '1', '0');
INSERT INTO `userinfo` VALUES ('3', 'admin', '1234', '1', '1');
2、项目案例的目录结构
3、com.util.BaseDB数据库通用类
public class BaseDB{
static String driver="com.mysql.cj.jdbc.Driver";
static String url="jdbc:mysql://localhost:3306/bbs?serverTimezone=UTC";
static String user="root";
static String pass="admin";
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException{
return DriverManager.getConnection(url,user,pass);
}
public ArrayList queryList(String sql,Object[] params) {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
ArrayList allData = new ArrayList();
try {
con = getConnection();
pstmt = con.prepareStatement(sql);
setParams(pstmt,params);
rs = pstmt.executeQuery();
int colCount = rs.getMetaData().getColumnCount();
while (rs.next()) {
ArrayList rowData = new ArrayList();
for (int i = 1; i <= colCount; i++) {
rowData.add(rs.getObject(i));
}
allData.add(rowData);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll(rs,pstmt,con);
}
return allData;
}
public List<Map> queryMap(String sql,Object[] params) {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
ArrayList allData = new ArrayList();
try {
con = getConnection();
pstmt = con.prepareStatement(sql);
setParams(pstmt,params);
rs = pstmt.executeQuery();
int colCount = rs.getMetaData().getColumnCount();
while (rs.next()) {
Map map=new LinkedHashMap();
for (int i = 1; i <= colCount; i++) {
map.put(rs.getMetaData().getColumnName(i),rs.getObject(i));
}
allData.add(map);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll(rs,pstmt,con);
}
return allData;
}
public int update(String sql,Object[] params) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConnection();
pstmt = con.prepareStatement(sql);
setParams(pstmt,params);
return pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll(null,pstmt,con);
}
return 0;
}
public void closeAll(ResultSet rs,Statement stmt,Connection con){
try {
if(rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
if(con!=null){
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void setParams(PreparedStatement ps,Object[] params)throws SQLException{
if(params==null) return;
for(int i=0;i<params.length;i++){
Object v=params[i];
ps.setObject(i+1,v);
}
}
}
4、项目案例中的通用类,用来存贮当前登录的用户信息,当前用户信息为了每个模块测试方便先设定一个管理员身份的用户,如果测试一般用户的话可以从新赋值,正常情况下应该是用户在登录成功后给它来赋值的。通用的打印List<Map>的方法
/**
* 该类用来存储一些在各个地方都要使用到的信息
* @author Justice
*
*/
public class UtilHelper {
/**
* 用来标记当前登录的用户,为测试方便先假定是管理员,系统正常运行时是在登录成功后将登录用户赋值给crrUser的
*/
public static Userinfo currUser=new Userinfo(3,"admin",1);
/**
* 将List<Map>的数据展示到控制台
* @param list<Map>:存放查询数据的列表
* @param bool:输出时是否打印列名
*/
public static void showList(List<Map> list,boolean bool,int grade) {
for(int i=0;i<grade;i++) {//按照输出的级别添加不同数量的\t
System.out.print("\t");
}
if(list.size()>0) {
if(bool) {
for(Object key:list.get(0).keySet()) {
System.out.print(key+"\t");
}
}
System.out.println();
for(Map map:list) {
for(Object key:map.keySet()) {
System.out.print(map.get(key)+"\t\t");
}
System.out.println();
}
}else {
System.out.println("没有找到你要的内容");
}
}
}
5、DAO层接口
BoardDao,UserDao,TopicDao,ReplyDao
以BoardDao为例
public interface BoardDao {
List<Map> findAllBoard();
Board findBorderByBname(String bname);
int addBoard(String boardName);
int updateBoard(int bid,String boardName);
int deleteBoard(int bid);
}
6、DAO接口实现类:BoardDaoImpl,该类仅仅实现了单个库表的操作
public class BoardDaoImpl implements BoardDao {
BaseDB base=new BaseDB();
@Override
/**
* 查找所有的板块
* 返回的集合类型是List<Map>
*/
public List<Map> findAllBoard() {
String sql="select * from board";
return base.queryMap(sql, null);
}
@Override
public Board findBorderByBname(String bname) {
String sql="select * from board where bname =?";
List<Map> list= base.queryMap(sql, new Object[] {bname});
Board board=null;
if(list.size()>0) {
Map map=list.get(0);
board=new Board((Integer)map.get("bid"),map.get("bname").toString());
}
return board;
}
@Override
public int addBoard(String boardName) {
String sql="insert into board values(null,?,?)";
return base.update(sql, new Object[] {boardName,1});
}
/**
* 根据板块id来修改板块的名称
* @param:boardName: 要修改的板块的新名称
*/
@Override
public int updateBoard(int bid,String boardName) {
String sql="update board set bname=? where bid=?";
return base.update(sql, new Object[] {boardName,bid});
}
/**
*该方法不是真正的删除,只是将板块的状态改为0(不可用)
*/
@Override
public int deleteBoard(int bid) {
String sql="update board set state=0 where bid="+bid;
return base.update(sql, null);
}
}
7、业务层实现,该层主要任务是业务实现,结合控制台的输入输出来完成具体的业务,结合每个实体单元的菜单导航业务。
public class BoardService {
static BoardDao bd=new BoardDaoImpl();
static Scanner sc=new Scanner(System.in);
public void boardMenu() {
while(true) {
System.out.println("板块管理");
System.out.println("---------------------");
System.out.println("1.所有板块\t 2.添加板块\t 3.修改版块\t 4.删除板块\t 5.退出板块管理");
System.out.println("---------------------");
switch(sc.nextInt()) {
case 1:
showAllBoard();
break;
case 2:
addBoard();
break;
case 3:
updateBoard();
break;
case 4:
deleteBoard();
break;
case 5:
System.out.println("退出板块管理");
return;
}
}
}
/**
* 将所有板块展示出来仅供浏览
*/
public void showAllBoard() {
List<Map> list=bd.findAllBoard();
UtilHelper.showList(list,true,0);
}
/**
* 根据输入的板块名称判断是否已经存在重名的板块,如果不存在重名则添加新板块
*/
private void addBoard() {
System.out.println("请输入板块名称");
String bname=sc.next();
Board board=bd.findBorderByBname(bname);
if(board!=null) {
System.out.println("板块名称已经存在");
return;
}
int count=bd.addBoard(bname);
if(count>0) {
System.out.println(bname+"板块添加完毕");
}
}
/**
* 根据输入的板块id将该板块名称修改为新输入的名称
*/
private void updateBoard() {
showAllBoard();
System.out.println("请输入要修改的板块编号");
int bid=sc.nextInt();
System.out.println("请输入要修改的板块名称");
String bname=sc.next();
int count=bd.updateBoard(bid,bname);
if(count>0) {
System.out.println(bname+"板块修改完毕");
}
if(count==0) {
System.out.println(bname+"板块没有找到");
}
}
/**
* 这里的删除仅仅是将板块的state设为0,即标记为不可用
*/
private void deleteBoard() {
showAllBoard();
System.out.println("请输入要删除的板块编号");
int bid=sc.nextInt();
int count=bd.deleteBoard(bid);
if(count>0) {
System.out.println("板块删除完毕");
}
if(count==0) {
System.out.println("没有找到删除的板块");
}
}
}
8、为了导航各种模块功能,需要一个导航菜单类,将每个模块的功能集中一起,形成导航菜单
/**
* 该类用来完成将各个模块功能汇总起来并进行导航,有三个模块菜单
* 1、登录、注册菜单 2、管理员菜单 3、一般用户菜单
* @author Justice
*
*/
public class Menu {
static Scanner sc=new Scanner(System.in);
static UserService us=new UserService();
static BoardService bs=new BoardService();
static TopicService ts=new TopicService();
static ReplyService rs=new ReplyService();
/**
* 用来进行登录和注册操作,只有正常登录后才能进入BBS系统,这是整个BBS系统的入口
*/
public static void loginMenu() {
System.out.println("欢迎登录BBS");
System.out.println("-------------------------------------");
System.out.println("1.登录\t 2.注册\t 3.退出");
System.out.println("-------------------------------------");
switch(sc.nextInt()) {
case 1://登录操作
int userType=us.userLogin();
if(userType==1) {
managerMenu(UtilHelper.currUser);
}
if(userType==0) {
userMenu(UtilHelper.currUser);
}
if(userType==-1) {
loginMenu();
}
break;
case 2://注册操作
int rcount=us.userRegist();
if(rcount==1) {
loginMenu();
}
break;
case 3:
System.out.println("您已退出BBS系统");
}
}
/**
* 管理员菜单,导航模块有:1.用户管理 2.板块管理 3.主贴管理 4.回复管理
* @param user
*/
public static void managerMenu(Userinfo user) {
while(true) {
System.out.println("欢迎你"+user.getUname()+"进入BBS后台管理系统");
System.out.println("-------------------------------------");
System.out.println("1.用户管理\t 2.板块管理\t 3.主贴管理\t 4.回复管理\t 5.退出系统");
System.out.println("-------------------------------------");
switch(sc.nextInt()) {
case 1:
us.userManagerMenu();
break;
case 2:
bs.boardMenu();
break;
case 3:
ts.topicMenu();
break;
case 4:
rs.replyMenu();
break;
case 5:
System.out.println("进入统计管理");
break;
case 6:
System.out.println("退出系统");
return;
}
}
}
/**
* 一般用户导航,只有两个功能模块:1.主贴 2.回复
* @param user
*/
public static void userMenu(Userinfo user) {
while(true) {
System.out.println("欢迎你"+user.getUname()+"进入BBS系统");
System.out.println("-------------------------------------");
System.out.println("1.主贴\t 2.回复\t 3.退出系统");
System.out.println("-------------------------------------");
int sid=sc.nextInt();
switch(sid) {
case 1:
ts.topicMenu();
break;
case 2:
rs.replyMenu();
break;
case 3:
System.out.println("退出系统");
return;
}
}
}
}