图书类别管理模块实现

1.数据库中新建一个t_type表,含有id和type_name属性,id为bigint类型,type_name为varchar类型。


类别表

输入一些图书类别


图书类别数据

2.纯后端实现

  • 实体类Type,在entity包,注意和以前的实体类的区别,使用了数据绑定属性
package com.soft1841.book.entity;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;

/**
 * 类别实体类
 */
public class Type {
    //以JavaFX属性绑定的形式,定义和数据表字段id和type_name对应的属性,注意命名规范
    private final SimpleLongProperty id = new SimpleLongProperty();
    private final SimpleStringProperty typeName = new SimpleStringProperty("");

    public Type() {
    }

    public Type(long id, String typeName) {
        setId(id);
        setTypeName(typeName);
    }

    public long getId() {
        return id.get();
    }

    public SimpleLongProperty idProperty() {
        return id;
    }

    public void setId(long id) {
        this.id.set(id);
    }

    public String getTypeName() {
        return typeName.get();
    }

    public SimpleStringProperty typeNameProperty() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName.set(typeName);
    }

    @Override
    public String toString() {
        return  typeName.get();
    }
}
  • DAO接口TypeDAO,在dao包,先写接口,再创建impl子包
package com.soft1841.book.dao;

import cn.hutool.db.Entity;
import com.soft1841.book.entity.Type;

import java.sql.SQLException;
import java.util.List;

/**
 * 图书类别DAO接口
 */
public interface TypeDAO {

    /**
     * 新增图书类别, 返回自增主键(Long)
     * @param type
     * @return
     */
    Long insertType(Type type) throws SQLException;

    /**
     * 根据id删除类别
     * @param id
     * @return
     */
    int deleteTypeById(long id) throws SQLException;

    /**
     * 查询所有类别
     * @return
     */
    List<Entity> selectAllTypes() throws SQLException;

    /**
     * 根据id查询类别信息
     * @param id
     * @return
     */
    Entity getTypeById(int id) throws SQLException;
}

  • DAO实现类,在dao下的impl子包
package com.soft1841.book.dao.impl;

import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.soft1841.book.dao.TypeDAO;
import com.soft1841.book.entity.Type;

import java.sql.SQLException;
import java.util.List;

public class TypeDAOImpl implements TypeDAO {

    @Override
    public Long insertType(Type type) throws SQLException {
        //采用了另一种新增方法,可以返回插入记录的主键(Long类型)
        return Db.use().insertForGeneratedKey(
                Entity.create("t_type")
                        .set("type_name", type.getTypeName())
        );
    }

    @Override
    public int deleteTypeById(long id) throws SQLException {
        return Db.use().del(
                Entity.create("t_type").set("id", id)
        );
    }


    @Override
    public List<Entity> selectAllTypes() throws SQLException {
        //1.采用默认的查询
        //return Db.use().findAll("t_type");
        //2.采用自定义查询语句查询
        return Db.use().query("SELECT * FROM t_type ");
    }

    @Override
    public Entity getTypeById(int id) throws SQLException {
        //采用自定义带参查询语句,返回单个实体
        return Db.use().queryOne("SELECT * FROM t_type WHERE id = ? ", id);
    }
}

  • 工厂类,在utils包,统一管理各个DAO接口,采用静态方法,这样无论在哪里调用,都是一个实例
package com.soft1841.book.utils;
import com.soft1841.book.dao.TypeDAO;
import com.soft1841.book.dao.impl.TypeDAOImpl;

/**
 * 工厂类,用静态方法来生成各个DAO实例
 */
public class DAOFactory {
    /**
     * 静态方法,返回TypeDAO实现类的对象
     * @return
     */
    public static TypeDAO getTypeDAOInstance() {
        return new TypeDAOImpl();
    }
}
  • 封装的组件类ComponentUtil ,用来在界面上生成“编辑”、“删除”等按钮
package com.soft1841.book.utils;

import javafx.scene.control.Button;

public class ComponentUtil {

    //根据传入的文字和主题返回一个按钮
    public static Button getButton(String text, String theme) {
        Button button = new Button(text);
        button.getStyleClass().add(theme);
        return button;
    }
}

  • 单元测试,测试TypeDAO接口中的各个方法,注意自己根据实际情况修改
package com.soft1841.book.dao;

import cn.hutool.db.Entity;
import com.soft1841.book.entity.Type;
import com.soft1841.book.utils.DAOFactory;
import org.junit.Test;

import java.sql.SQLException;
import java.util.List;

public class TypeDAOTest {
    //通过DAO工厂获得TypeDAO的实例
    private TypeDAO typeDAO = DAOFactory.getTypeDAOInstance();

    @Test
    public void insertType() throws SQLException {
        Type type = new Type();
        type.setTypeName("测试类别");
        System.out.println(typeDAO.insertType(type));
    }

    @Test
    public void deleteTypeById() throws SQLException {
        typeDAO.deleteTypeById(7);
    }

    @Test
    public void selectAllTypes() throws SQLException {
        List<Entity> typeList = typeDAO.selectAllTypes();
        typeList.forEach(entity -> System.out.println(entity));
    }

    @Test
    public void getTypeById() throws SQLException {
        Entity entity = typeDAO.getTypeById(1);
        System.out.println(entity);
    }
}

3.界面

  • type.fxml布局文件,是左侧导航点击“类别管理”->“图书类别”切换的内容,调用的控制器是TypeController
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<AnchorPane xmlns="http://javafx.com/javafx"
           xmlns:fx="http://javafx.com/fxml"
           fx:controller="com.soft1841.book.controller.TypeController">
   <HBox AnchorPane.topAnchor="10" AnchorPane.leftAnchor="20" spacing="20">
       <Button text="添加图书类别" styleClass="green-theme" onAction="#addType"/>
   </HBox>
   <!--表格视图,用来显示数据库中查询到的图书类别-->
   <TableView fx:id="typeTable" prefWidth="700"
              AnchorPane.leftAnchor="20" AnchorPane.topAnchor="50">
       <columns>
           <!--ID列-->
           <TableColumn text="ID">
               <!--绑定实体类中的id属性-->
               <cellValueFactory>
                   <PropertyValueFactory property="id"/>
               </cellValueFactory>
           </TableColumn>
           <!--类别名称列-->
           <TableColumn text="类别名称">
               <!--绑定实体类中的typeName属性-->
               <cellValueFactory>
                   <PropertyValueFactory property="typeName"/>
               </cellValueFactory>
           </TableColumn>
       </columns>
   </TableView>
</AnchorPane>
  1. 图书类别控制器TypeController.java,用来创建模型数据,和数据库查询的类别数据做绑定后在表格输出。控制器是前后端联系的桥梁
package com.soft1841.book.controller;
import cn.hutool.db.Entity;
import com.soft1841.book.dao.TypeDAO;
import com.soft1841.book.entity.Type;
import com.soft1841.book.utils.ComponentUtil;
import com.soft1841.book.utils.DAOFactory;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;

import java.net.URL;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;

public class TypeController implements Initializable {
    //获得布局文件中的表格对象
    @FXML
    private TableView<Type> typeTable;

    //定义ObservableList数据集合
    private ObservableList<Type> typeData = FXCollections.observableArrayList();

    //通过工厂类获得TypeDAO的实例
    private TypeDAO typeDAO = DAOFactory.getTypeDAOInstance();

    //定义实体集合,用来存放数据库查询结果
    private List<Entity> entityList = null;

    private TableColumn<Type, Type> delCol = new TableColumn<>("操作");


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //水平方向不显示滚动条
        typeTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        //在表格最后加入删除按钮
        delCol.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
        delCol.setCellFactory(param -> new TableCell<Type, Type>() {
            private final Button deleteButton = ComponentUtil.getButton("删除", "warning-theme");
            @Override
            protected void updateItem(Type type, boolean empty) {
                super.updateItem(type, empty);
                if (type == null) {
                    setGraphic(null);
                    return;
                }
                setGraphic(deleteButton);
                //点击删除按钮,需要将这一行从表格移除,同时从底层数据库真正删除
                deleteButton.setOnAction(event -> {
                    //删除操作之前,弹出确认对话框,点击确认按钮才删除
                    Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
                    alert.setTitle("确认对话框");
                    alert.setHeaderText("请确认");
                    alert.setContentText("确定要删除这行记录吗?");
                    Optional<ButtonType> result = alert.showAndWait();
                    //点击了确认按钮,执行删除操作,同时移除一行模型数据
                    if (result.get() == ButtonType.OK){
                        typeData.remove(type);
                        try {
                            typeDAO.deleteTypeById(type.getId());
                        } catch (SQLException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
        //删除列加入表格
        typeTable.getColumns().add(delCol);
        try {
            entityList = typeDAO.selectAllTypes();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        showTypeData(entityList);
    }

    public void addType() {
        //创建一个输入对话框
        TextInputDialog dialog = new TextInputDialog("新类别");
        dialog.setTitle("图书类别");
        dialog.setHeaderText("新增图书类别");
        dialog.setContentText("请输入图书类别名称:");
        Optional<String> result = dialog.showAndWait();
//        result.ifPresent(name -> System.out.println("你的输入: " + name));
        //确认输入了内容
        if (result.isPresent()) {
            //获得输入的内容
            String typeName = result.get();
            //创建一个Type对象,插入数据库,并返回主键
            Type type = new Type();
            type.setTypeName(typeName);
            long id = 0;
            try {
                id = typeDAO.insertType(type);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            type.setId(id);
            //加入ObservableList,刷新模型视图,不用重新查询数据库也可以立刻看到结果
            typeData.add(type);

        }
    }

    private void showTypeData(List<Entity> entityList) {
        //遍历实体集合
        for (Entity entity : entityList) {
            //取出属性,创建Type的对象
            Type type = new Type();
            type.setId(entity.getInt("id"));
            type.setTypeName(entity.getStr("type_name"));
            //加入ObservableList模型数据集合
            typeData.add(type);
        }
        typeTable.setItems(typeData);
    }

}

5.图书类别管理实现效果
可以查看所有类别,新增、删除,并且无需手动刷新。删除之前有提示信息。


image.png
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 今天和大家分享的模式是解释器模式。 首先介绍一下解释器模式适合解决哪类问题。 其实,解释器模式需要解决的问题是,如...
    泥孩儿0107阅读 342评论 0 0
  • 左边的电梯下去就是地铁口,实在是方便到家了! 购票窗口 看完电影,下次光临! 帮人写文章,稿酬是一张苏州科文...
    苏州的蔷薇花开阅读 746评论 9 6
  • 春天到了,天气转暖,万物复苏。阳光不错,把我的小朋友都拿出来晒一晒,一起沐浴阳光。️️️️️️️️️
    皇脚丫阅读 135评论 0 0