Mi informacion de contacto
Correo[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
JavaWeb (1: Conocimientos básicos y construcción del entorno)https://blog.csdn.net/xpy2428507302/article/details/140365130?spm=1001.2014.3001.5501JavaWeb (2: Servlet y Jsp, oyente y filtro)
https://blog.csdn.net/xpy2428507302/article/details/140365159?spm=1001.2014.3001.5501
Tabla de contenido
(4) clase Conjunto de resultados
7. Grupo de conexiones de base de datos
11. Arquitectura MVC de tres niveles
Segundo, arquitectura de tres niveles mvc
JDBC (Java DataBase Connectivity): tecnología de conexión de bases de datos Java
JDBC es un sistema de gestión independiente de una base de datos específica y una interfaz pública para operaciones y acceso universal a bases de datos SQL.
Define un conjunto de estándares para proporcionar una forma unificada de acceder a diferentes bases de datos.
JDBC es una API de aplicación para acceso a bases de datos, que consta de un conjunto de clases e interfaces escritas en lenguaje Java.
Incluye dos niveles:
① API orientada a aplicaciones para que la llamen los programadores.
② API orientada a bases de datos para que los fabricantes desarrollen controladores de bases de datos.
Para conectar diferentes bases de datos con JDBC, solo necesita cargar diferentes paquetes de controladores de bases de datos y no tiene que preocuparse por las diferencias en los lenguajes operativos de las bases de datos.
① Crear tabla de base de datos
- CREATE TABLE users(
- id INT PRIMARY KEY,
- `name` VARCHAR(40),
- `password` VARCHAR(40),
- email VARCHAR(60),
- birthday DATE
- );
- INSERT INTO users(id,`name`,`password`,email,birthday)
- INSERT INTO users(id,`name`,`password`,email,birthday)
- INSERT INTO users(id,`name`,`password`,email,birthday)
- SELECT * FROM users;
② Importar dependencias de bases de datos
- <!--mysql的驱动-->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>8.0.31</version>
- </dependency>
③ Uso de JDBC:
Ⅰ Cargue el controlador de la base de datos (el puente entre el programa Java y la base de datos).
Ⅱ Obtener conexión, una conexión entre el programa Java y la base de datos.
Ⅲ Crear un objeto Statement que envíe SQL a la base de datos, generado por Connection.
Ⅳ Escribir sentencias SQL (escribir diferentes SQL según el negocio)
Ⅴ Ejecute SQL (si desea recibir el valor de retorno, cree un objeto ResultSet para guardar los resultados de la consulta después de ejecutar la Declaración)
Ⅵ. Cerrar la conexión
- public class JDBCTest {
- public static void main(String[] args) throws Exception {
- //配置信息
- //要连接的数据库URL(解决中文乱码问题:useUnicode=true&characterEncoding=utf8&useSSL=true)
- String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=true";
- //连接的数据库时使用的用户名
- String username = "root";
- //连接的数据库时使用的密码
- String password = "123456";
- Connection conn = null;
- Statement st = null;
- ResultSet rs = null;
-
- try {
- //1.加载驱动
- Class.forName("com.mysql.cj.jdbc.Driver");
- //2.获取与数据库的链接
- conn = DriverManager.getConnection(url, username, password);
- //3.获取用于向数据库发送sql语句的statement对象
- st = conn.createStatement();
- String sql = "select id,name,password,email,birthday from users";
- //4.向数据库发sql,并获取代表结果集的resultset对象
- //查:executeQuery 增删改:executeUpdate
- rs = st.executeQuery(sql);
- //5.取出结果集的数据
- while (rs.next()) {
- System.out.println("id=" + rs.getInt("id"));
- System.out.println("name=" + rs.getString("name"));
- System.out.println("password=" + rs.getString("password"));
- System.out.println("email=" + rs.getString("email"));
- System.out.println("birthday=" + rs.getDate("birthday"));
- }
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- try {
- //6.关闭链接,释放资源(先开后关)
- rs.close();
- st.close();
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
jdbc:mysql://localhost:3306/xxx
JDBC | protocolo |
MySQL | subprotocolo |
host local:3306 | Puerto host |
xxx | base de datos |
Cómo escribir direcciones URL de bases de datos de uso común:
La conexión se utiliza para representar enlaces de bases de datos y la colección es el objeto más importante en la programación de bases de datos.
Todas las interacciones entre el cliente y la base de datos se completan a través del objeto de conexión., métodos comunes de este objeto:
crearDeclaración() | Cree un objeto de declaración que envíe SQL a la base de datos. |
prepararDeclaración(sql) | Cree un objeto PrepareStement que envíe SQL precompilado a la base de datos |
setAutoCommit(booleano autoCommit) | Establecer si las transacciones se confirman automáticamente |
comprometerse() | Enviar transacción en enlace |
Retroceder() | Revertir transacción en este enlace |
El objeto Statement se utiliza para enviar sentencias SQL a la base de datos. Métodos comunes del objeto Statement:
ejecutarConsulta(Cadena sql) | Se utiliza para enviar declaraciones de consulta a datos y devolver un conjunto de resultados ResultSet |
ejecutarActualizar(Cadena sql) | Se utiliza para enviar declaraciones de inserción, actualización o eliminación a la base de datos y devolver el número de filas actualizadas en la base de datos. |
ejecutar(Cadena sql) | Se utiliza para enviar declaraciones SQL arbitrarias a la base de datos. |
addBatch(Cadena sql) | Ponga varias declaraciones SQL en un lote |
ejecutarBatch() | Envíe un lote de declaraciones SQL a la base de datos para su ejecución. |
Aviso:
Para mejorar la eficiencia operativa, el método de ejecución generalmente no se utiliza directamente.
En su lugar, utilícelos en consecuencia: ejecutarQuery para consultas; ejecutarUpdate para adiciones, eliminaciones y modificaciones.
ResultSet se utiliza para representar los resultados de ejecución de declaraciones Sql.
Conjunto resultante Al encapsular el conjunto de resultados de ejecución, utilicesimilar a la mesaEl camino。
El objeto ResultSet mantiene un cursor que apunta a las filas de datos de la tabla.Inicialmente, el cursor está antes de la primera fila.。
Llamar al método ResultSet.next() puede hacer que el cursor apunte a una fila de datos específica y llamar al método getxxx para obtener los datos de la fila.
① Obtener cualquier tipo de datos
obtenerObjeto(int índice) | Obtenga el objeto Objeto según el número especificado de columnas |
obtenerObjeto(cadena nombreColumna) | Obtenga el objeto Objeto según el nombre del atributo especificado |
② Obtener datos de un tipo específico, como obtener el tipo de cadena
getString(int índice) | Obtenga un objeto String basado en el número especificado de columnas |
getString(Cadena nombreColumna) | Obtenga el objeto String según el nombre del atributo especificado |
③ Cómo desplazar el conjunto de resultados:
próximo() | pasar a la siguiente línea |
Anterior() | pasar a la línea anterior |
absoluto(int fila) | Mover a la línea especificada |
antes dePrimero() | Mover el frente del conjunto de resultados |
después del último() | Ir al final del conjunto de resultados |
Una vez que el programa Jdbc haya terminado de ejecutarse, recuerde liberar los objetos creados por el programa para interactuar con la base de datos durante el proceso de ejecución.
Estos objetos suelen ser objetos ResultSet, Statement y Connection.
Especialmente el objeto Conexión, es un recurso muy raro y debe liberarse inmediatamente después de su uso.
Si la conexión no se puede cerrar rápida y correctamente, puede provocar fácilmente un tiempo de inactividad del sistema.
Para garantizar que el código de liberación del recurso se pueda ejecutar, el código de liberación del recurso también debe colocarse en la declaración finalmente.
Hay dos problemas al usar Statement para desarrollo:
① Las cadenas deben empalmarse con frecuencia y la tasa de error es alta
- String username = "zhangsan";
- String password = "123";
- String sql = "select * from users where name='"+username+"' and password='"+password+"'";
- ResultSet rs = st.executeQuery(sql);
② Existe un riesgo potencial de inyección SQL
Inyección de SQL: inyectar declaraciones SQL ilegales en los datos ingresados por el usuario, utilizando técnicas inteligentes para unir cadenas, provocando un cortocircuito de SQL y robando así datos de la base de datos.
- public class SQLTest {
- public static void main(String[] args) throws Exception {
- // 正常登陆sql:select * from users where name='张三' and password ='123456'
- //login("张三","123456");
- // SQL 注入:select * from users where name='' and password ='123456' or '1'='1'
- login("", "123456' or '1'='1");
- }
-
- public static void login(String username, String password) throws Exception {
- String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=true";
- String dbUsername = "root";
- String dbPassword = "123456";
-
- //1.加载驱动
- Class.forName("com.mysql.cj.jdbc.Driver");
- //2.获取与数据库的链接
- Connection conn = DriverManager.getConnection(url, dbUsername, dbPassword);
- //3.获取用于向数据库发送sql语句的statement
- Statement st = conn.createStatement();
- String sql = "select * from users where name='" + username + "' and password='" + password + "'";
- System.out.println(sql);
- //4.向数据库发sql,并获取代表结果集的rs
- ResultSet rs = st.executeQuery(sql);
- if (rs.next()) {
- System.out.println("登录成功");
- } else {
- System.out.println("登录失败");
- }
- //6.关闭链接,释放资源
- rs.close();
- st.close();
- conn.close();
- }
- }
resultado de la operación:
Aviso:
La prioridad de y en la declaración SQL es mayor que o, por lo que el SQL ejecutado equivale a seleccionar * de los usuarios donde '1' = '1';
Solución:Utilice PreparedStatement, una subclase de Statement, que proporciona la función de marcador de posición SQL.
No es necesario unir cadenas y los datos ingresados por el usuario se detectarán completamente, lo que lo hará más seguro.
- public class PSTest {
- public static void main(String[] args) throws Exception {
- // 正常登陆sql:select * from users where name='张三' and password ='123456'
- //login("张三","123456");
- // SQL 注入:select * from users where name='' and password ='123456' or '1'='1'
- login("", "123456' or '1'='1");
- }
-
- public static void login(String username, String password) throws Exception {
- String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=true";
- String dbUsername = "root";
- String dbPassword = "123456";
-
- Class.forName("com.mysql.cj.jdbc.Driver");
-
- Connection conn = DriverManager.getConnection(url, dbUsername, dbPassword);
- //获取用于向数据库发送预编译sql语句的prepareStatement
- String sql = "select * from users where name = ? and password = ?";
- System.out.println(sql);
- PreparedStatement ps = conn.prepareStatement(sql);
- //给占位符 ? 填充数据
- ps.setString(1, username);
- ps.setString(2, password);
- ResultSet rs = ps.executeQuery();
- if (rs.next()) {
- System.out.println("登录成功");
- } else {
- System.out.println("登录失败");
- }
- rs.close();
- ps.close();
- conn.close();
- }
- }
resultado de la operación:
Una transacción se refiere a un conjunto lógico de operaciones, ya sea todas exitosas o todas fallidas (principio ACID).
Cuando el programa Jdbc obtiene un objeto Connection de la base de datos, de forma predeterminada, el objeto Connection enviará automáticamente una transacción a la base de datos.
Si desea desactivar este método de envío predeterminado y permitir que se ejecuten varios SQL en una transacción, puede utilizar la siguiente declaración de transacción de control JDBC.
Conexión.setAutoCommit(false); | iniciar transacción |
Conexión.rollback(); | Transacción de reversión |
Conexión.commit(); | confirmar transacción |
① Crear tabla de cuentas
- /*创建账户表*/
- CREATE TABLE account(
- id INT PRIMARY KEY AUTO_INCREMENT,
- NAME VARCHAR(40),
- money DECIMAL(9,2)
- );
- /*插入测试数据*/
- insert into account(name,money) values('A',1000);
- insert into account(name,money) values('B',1000);
- insert into account(name,money) values('C',1000);
② Simule el escenario empresarial cuando la transferencia sea exitosa
- //失败后让数据库自动回滚事务
- public class Demo {
- public static void main(String[] args) {
- String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=true";
- String username = "root";
- String password = "123456";
- Connection conn = null;
- try {
- Class.forName("com.mysql.cj.jdbc.Driver");
- conn = DriverManager.getConnection(url, username, password);
-
- //通知数据库开启事务,false表示开启
- conn.setAutoCommit(false);
-
- String sql1 = "update account set money=money-100 where name = 'A' ";
- conn.prepareStatement(sql1).executeUpdate();
-
- //模拟执行完SQL1之后程序出现了异常而导致后面的SQL无法正常执行,事务也无法正常提交
- int x = 1/0;
-
- String sql2 = "update account set money=money+100 where name = 'B' ";
- conn.prepareStatement(sql2)executeUpdate();
-
- //sql1 和 sql2都顺利执行,就提交事务
- conn.commit();
- System.out.println("成功!!!");
- } catch (Exception e) {
- //出现异常,通知数据库回滚事务
- conn.rollback();
- e.printStackTrace();
- } finally {
- conn.close();
- }
- }
- }
En diferentes solicitudes, debe conectarse a la base de datos y liberar recursos cada vez, y se escribirá una gran cantidad de código repetido.
Encapsule las operaciones de preparación y liberación de la conexión de la base de datos en una clase de herramienta y llámela directamente cuando la use para evitar escribir código repetido.
- public class JdbcUtil {
- private static Connection connection;
- private static String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=true";
- private static String username = "root";
- private static String password = "123456";
-
- //驱动(类)只需要加载一次,放静态代码块即可
- static {
- try {
- //加载数据库驱动
- Class.forName("com.mysql.cj.jdbc.Driver");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- // 获取数据库连接对象
- public static Connection getConnection() throws SQLException {
- return DriverManager.getConnection(url, username, password);
- }
-
- // 释放资源(利用多态:Statement 和 PreparedStatement 都可以传进来)
- public static void release(Connection conn, Statement st, ResultSet rs) {
- try {
- if (rs != null) {
- rs.close();
- }
- if (st != null) {
- st.close();
- }
- if (conn != null) {
- conn.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
Caso de llamada, como: agregar usuario
-
- public void add(String name, String password) {
- Connection conn = null;
- PreparedStatement ps = null;
- try {
- conn = JdbcUtil.getConnection();
- String sql = "insert into users(name,password) values(?,?)";
- ps = conn.prepareStatement(sql);
- ps.setString(1, name);
- ps.setString(2, password);
- ps.executeUpdate();
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- JdbcUtil.release(conn, ps, null);
- }
- }
Proceso de desarrollo de JDBC:
Ⅰ Cargue el controlador de la base de datos (solo es necesario cargarlo una vez).
Ⅱ Establecer conexión de base de datos (Conexión)
Ⅲ Crear un objeto Statement que envíe SQL a la base de datos, generado por Connection.
Ⅳ Escribir sentencias SQL
Ⅴ Ejecutar SQL (Consulta-->El objeto ResultSet recibe el conjunto de resultados)
Ⅵ. Cerrar la conexión y liberar recursos.
El objeto de conexión de la base de datos se obtiene a través de DriverManager. Cada vez que se obtiene, debe solicitar una conexión a la base de datos y verificar el nombre de usuario y la contraseña.
Los usuarios necesitan obtener un enlace de la base de datos para cada solicitud, y crear una conexión a la base de datos generalmente consume recursos relativamente grandes y lleva mucho tiempo crearla.
Cada vez que se ejecuta la instrucción SQL, la conexión se desconecta, lo que provocará un desperdicio de recursos y los recursos de conexión de la base de datos no se reutilizarán bien.
Suponiendo que el sitio web recibe 100.000 visitas al día, el servidor de la base de datos necesita crear 100.000 conexiones, lo que supone un enorme desperdicio de recursos de la base de datos y puede provocar fácilmente un desbordamiento de la memoria del servidor de la base de datos y una expansión de la máquina.
Solución: grupo de conexiones de base de datos
La idea básica del grupo de conexiones de bases de datos:
Establezca un grupo de búfer para la base de datos y coloque una cierta cantidad de objetos de conexión en el grupo de búfer de antemano.
Cuando desee obtener una conexión a la base de datos, solo necesita tomar un objeto del grupo de búfer.
Después de su uso, vuelva a colocarlo en el grupo de búfer para usarlo en la siguiente solicitud, logrando la reutilización de recursos sin la necesidad de crearlos repetidamente.
Cuando no hay objetos de conexión inactivos en el grupo de conexiones de la base de datos, las nuevas solicitudes ingresarán a la cola de espera y esperarán a que otros subprocesos liberen la conexión.
El grupo de conexiones de la base de datos de JDBC se completa utilizando la interfaz javax.sql.DataSource. DataSource es la interfaz proporcionada oficialmente por Java.
Al usarlo, los desarrolladores no necesitan implementar la interfaz ellos mismos y pueden utilizar herramientas de terceros.
C3P0 es una implementación de terceros de uso común. En el desarrollo real, C3P0 se puede usar directamente para completar la operación del grupo de conexiones de la base de datos.
Pasos de uso:
① Importar dependencias en pom.xml
- <dependency>
- <groupId>com.mchange</groupId>
- <artifactId>c3p0</artifactId>
- <version>0.9.5.2</version>
- </dependency>
② Escribir código
- public class DataSourceTest {
- public static void main(String[] args) {
- try {
- //创建C3P0数据库连接池
- ComboPooledDataSource dataSource=new ComboPooledDataSource();
- dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
- dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8");
- dataSource.setUser("root");
- dataSource.setPassword("123456");
- //设置初始化连接个数
- dataSource.setInitialPoolSize(5);
- //设置最大连接个数(连接池中不够,可以继续申请,申请后最终的上限)
- dataSource.setMaxPoolSize(20);
- //当连接对象不够时,再次申请的连接对象个数
- dataSource.setAcquireIncrement(5);
- //设置最小连接数(当连接池中剩余2个连接对象时,就去申请 --> 提前做准备)
- dataSource.setMinPoolSize(2);
- Connection conn=dataSource.getConnection();
-
- //SQL操作...
-
- //将连接还回到数据库连接池中
- conn.close();
- } catch (PropertyVetoException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
Aviso:
Conexión obtenida mediante método tradicional: com.mysql.cj.jdbc.ConnectionImpl@3c153a1
Conexión obtenida por C3P0: com.mchange.v2.c3p0.impl.NewProxyConnection@6156496
entonces,Aunque todos llaman al método de cierre, las clases de implementación son diferentes, por lo que la reescritura del método también es diferente. Esto es polimorfismo de interfaz.。
El método de cierre en C3P0 no destruye directamente el recurso de conexión, sino que devuelve la conexión al grupo de conexiones de la base de datos.
El método anterior para configurar los parámetros del grupo de conexiones de la base de datos está escrito directamente en el programa Java.
esto es adoptadoCódigo difícilEl camino,Cada vez que cambias la configuraciónNecesidad de recompilar, genera nuevos archivos de clase, la eficiencia es demasiado baja。
En el desarrollo real, la información de configuración de C3P0 se define en un archivo xml y el programa Java solo necesita cargar el archivo de configuración para completar la operación de inicialización del grupo de conexiones de la base de datos.
Posteriormente, solo necesita modificar la configuración y modificar la configuración en xml sin volver a compilar.
Pasos de uso:
① En el directorio de recursos, cree un nuevo archivo llamado c3p0-config.xml
② Complete la información de configuración en c3p0-config.xml:
- <?xml version="1.0" encoding="UTF-8"?>
- <c3p0-config>
- <!--配置连接池mysql-->
- <named-config name="C3P0Test">
- <!-- 指定连接数据源的基本属性 -->
- <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
- <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8</property>
- <property name="user">root</property>
- <property name="password">123456</property>
-
- <!-- 设置初始化连接个数 -->
- <property name="initialPoolSize">5</property>
- <!-- 设置最大连接个数(连接池中不够,可以继续申请,申请后最终的上限) -->
- <property name="maxPoolSize">20</property>
- <!-- 当连接对象不够时,再次申请的连接对象个数 -->
- <property name="acquireIncrement">5</property>
- <!-- 设置最小连接数(当连接池中剩余2个连接对象时,就去申请 -> 提前做准备) -->
- <property name="minPoolSize">2</property>
- </named-config>
- </c3p0-config>
③Escribir programa Java
- public class DataSourceTest {
- public static void main(String[] args) {
- try {
- //创建C3P0数据库连接池
- ComboPooledDataSource dataSource=new ComboPooledDataSource("C3P0Test");
- Connection conn=dataSource.getConnection();
- System.out.println(conn);
- //将连接还回到数据库连接池中
- conn.close();
- }catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
Aviso:
① El parámetro en el método de construcción ComboPooledDataSource es el valor del atributo de nombre de la etiqueta de configuración nombrada configurada en c3p0-config.xml.
② En este momento, la clase de herramienta JDBC se puede modificar como:
- public class JdbcUtil {
- private static DataSource dataSource;
-
- static {
- dataSource = new ComboPooledDataSource("C3P0Test");
- }
-
- // 获取数据库连接对象
- public static Connection getConnection() throws SQLException {
- Connection conn = null;
- try {
- conn = dataSource.getConnection();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return conn;
- }
-
- // 释放资源(利用多态:Statement 和 PreparedStatement 都可以传进来)
- public static void release(Connection conn, Statement st, ResultSet rs) {
- try {
- if (rs != null) {
- rs.close();
- }
- if (st != null) {
- st.close();
- }
- if (conn != null) {
- conn.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- public static Student findById(Integer idx) {
- Connection conn = null;
- PreparedStatement st = null;
- ResultSet rs = null;
- Student stu = null;
- try {
- conn = JdbcUtil.getConnection();
-
- String sql = "select * from student where id = ?";
- PreparedStatement ps = conn.prepareStatement(sql);
- //给占位符 ? 填充数据
- ps.setInt(1, idx);
- rs = ps.executeQuery();
- //取出结果集的数据
- while (rs.next()) {
- Integer id = rs.getInt(1);
- String name = rs.getString(2);
- Double score = rs.getDouble(3);
- Date birthday = rs.getDate(4);
- stu = new Student(id, name, score, birthday);
- }
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- try {
- //关闭链接,释放资源
- rs.close();
- st.close();
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- return stu;
- }
En el código anterior, las operaciones de llenar los marcadores de posición con datos y extraer los datos del conjunto de resultados son demasiado engorrosas.
Si hay 100 atributos en la tabla Student, entonces tendremos que escribir 100 filas en el bucle while para recuperar los datos, y también es posible que se necesiten muchas filas para completar los marcadores de posición.
Solución:DBUtils puede ayudar a los desarrolladores a completar la encapsulación de datos (asignación de conjuntos de resultados a objetos Java).
Pasos de uso:
① Importar dependencias en pom.xml
- <dependency>
- <groupId>commons-dbutils</groupId>
- <artifactId>commons-dbutils</artifactId>
- <version>1.6</version>
- </dependency>
② Escribir código
- public static Student findById(Integer idx) {
- Connection conn = null;
- Student stu = null;
- try {
- conn = JdbcUtil.getConnection();
-
- String sql = "select * from student where id = ?";
- //使用DBUtils
- QueryRunner qr = new QueryRunner();
- stu = qr.query(conn, sql, new BeanHandler<>(Student.class), idx);
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- try {
- //关闭链接,释放资源
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- return stu;
- }
En este punto, llenar los marcadores de posición y extraer el conjunto de resultados se puede lograr con dos líneas de código.
detalle:
① El método de consulta debe pasar 4 parámetros:
Objeto de conexión
declaración SQL
El objeto de clase de implementación de la interfaz ResultSetHandler (el tipo de objeto convertido debe ser: Student.class)
Parámetros para completar marcadores de posición
② La interfaz ResultSetHandler se utiliza para procesar conjuntos de resultados. Puede convertir los conjuntos de resultados consultados en objetos Java. Se proporcionan las siguientes cuatro clases de implementación.
Manejador de frijoles | Asigne el conjunto de resultados a un objeto Java (como el objeto Estudiante) |
Manejador de BeanList | Asigne el conjunto de resultados a una colección de Lista (como: Lista<Student > ) |
Manejador de mapas | Asigne el conjunto de resultados a un objeto de colección de mapas (es decir: mapa<String,Object> clave: nombre del atributo; valor del atributo) |
Manejador de listas de mapas | Asigne el conjunto de resultados a una colección MapList (es decir: Lista <Map<<String,Object> >) |
③ El parámetro para completar el marcador de posición es un parámetro variable, por lo que se puede pasar cualquier cantidad de parámetros para satisfacer las diferentes necesidades de los usuarios.
④ La clase de objeto convertida (clase de Estudiante) debe tener un constructor sin parámetros; de lo contrario, el programa informará un error.
razón:La capa inferior encuentra esta clase a través de Student.class y luego a través demecanismo de reflexiónEncuentre el constructor sin parámetros de esta clase y cree su objeto.
⑤ El nombre del atributo en la clase debe ser exactamente el mismo que el nombre del campo en la tabla de la base de datos.
Porque una vez creado el objeto, al asignar valores a las propiedades del objeto en función del conjunto de resultados, la búsqueda y asignación se realizan en función del nombre.
¿Qué es MVC?
Después de que la solicitud ingresa a la aplicación JavaWeb, el Controlador recibe la solicitud, realiza el procesamiento de la lógica de negocios y finalmente devuelve el resultado al usuario (Ver + Modelo).
En los primeros años, al operar aplicaciones web, los usuarios accedían directamente a la capa de control, y la capa de control podía operar directamente la base de datos:
servlet--CRUD (agregar, eliminar, modificar)-->base de datos
En el código del servlet: procesamiento de solicitudes, respuestas, saltos de vista, procesamiento JDBC, procesamiento de código comercial y procesamiento de código lógico.
Desventajas:El programa está muy inflado y no es propicio para el mantenimiento.
solución: No hay nada que agregar otra capa no pueda resolver, si es así, ¡agrega otra capa!
Modelo
vista
Controlador (Servlet)
Tome el inicio de sesión de usuario y administrador como ejemplo:
Capa controladora:
- @WebServlet("/login")
- public class LoginServlet extends HttpServlet {
-
- private LoginService loginService = new LoginServiceImpl();
-
- /* 处理登录的业务逻辑*/
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String username = req.getParameter("username");
- String password = req.getParameter("password");
- String type = req.getParameter("type");
- Object object = loginService.login(username,password,type);
- if(object != null){
- HttpSession session = req.getSession();
- switch (type){
- case "reader":
- Reader reader = (Reader) object;
- session.setAttribute("reader",reader);
- //跳转到用户的首页
- resp.sendRedirect("/book?page=1");
- break;
- case "admin":
- Admin admin = (Admin) object;
- session.setAttribute("admin",admin);
- //跳转到管理员的首页
- resp.sendRedirect("/admin?method=findAllBorrow&page=1");
- break;
- }
- }else{
- resp.sendRedirect("login.jsp");
- }
- }
-
- }
Capa de servicio:
- public interface LoginService {
- //利用多态,动态返回不同类型的对象
- public Object login(String username,String password,String type);
- }
- public class LoginServiceImpl implements LoginService {
-
- private ReaderRepository readerRepository = new ReaderRepositoryImpl();
- private AdminRepository adminRepository = new AdminRepositoryImpl();
-
- @Override
- public Object login(String username, String password,String type) {
- Object object = null;
- //业务逻辑处理:根据type的值,来选择调用不同的登录方法,去查找不同的表
- switch (type){
- case "reader":
- object = readerRepository.login(username,password);
- break;
- case "admin":
- object = adminRepository.login(username, password);
- break;
- }
- return object;
- }
- }
Capa Dao/Repositorio:
- public interface AdminRepository {
- public Admin login(String username,String password);
- }
- public interface ReaderRepository {
- public Reader login(String username,String password);
- }
- public class AdminRepositoryImpl implements AdminRepository {
- //管理员的登录方法(和数据库交互)
- @Override
- public Admin login(String username, String password) {
- Connection connection = JDBCTools.getConnection();
- String sql = "select * from bookadmin where username = ? and password = ?";
- PreparedStatement statement = null;
- ResultSet resultSet = null;
- Admin admin = null;
- try {
- statement = connection.prepareStatement(sql);
- statement.setString(1,username);
- statement.setString(2,password);
- resultSet = statement.executeQuery();
- if(resultSet.next()){
- admin = new Admin(resultSet.getInt(1),resultSet.getString(2),resultSet.getString(3));
- }
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- JDBCTools.release(connection,statement,resultSet);
- }
- return admin;
- }
- }
- public class ReaderRepositoryImpl implements ReaderRepository {
- //用户的登录方法(和数据库交互)
- @Override
- public Reader login(String username, String password) {
- Connection connection = JDBCTools.getConnection();
- String sql = "select * from reader where username = ? and password = ?";
- PreparedStatement statement = null;
- ResultSet resultSet = null;
- Reader reader = null;
- try {
- statement = connection.prepareStatement(sql);
- statement.setString(1,username);
- statement.setString(2,password);
- resultSet = statement.executeQuery();
- if(resultSet.next()){
- reader = new Reader(resultSet.getInt(1),resultSet.getString(2),resultSet.getString(3),resultSet.getString(4),resultSet.getString(5),resultSet.getString(6),resultSet.getString(7));
- }
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- JDBCTools.release(connection,statement,resultSet);
- }
- return reader;
- }
- }