ssm-day04 mybatis

mybatis是一个持久层框架,针对的是JDBC的优化

简化数据库操作,能进行单表、多表操作,在这个框架下,需要我们自己写SQL语句

Mapper接口和MapperXML文件就相当于Dao和Dao层的实现

通常将xml文件放在resources包下 ,放在Java文件maven不会打包

DTD(Document Type Definition,文档类型定义)是一种用于定义XML文档结构和内容规则的技术。它描述了允许的元素、属性、实体以及它们之间的关系,从而确保XML文档遵循特定的格式。DTD可以内嵌在XML文档中,也可以作为外部文件引用。以下是关于DTD约束的一些关键点:

一、DTD的作用

  1. 定义元素:指定哪些元素可以在文档中出现,以及这些元素可以包含什么内容。
  2. 定义属性:为元素定义可能的属性及其值的类型(如CDATA、ID、IDREF等)。
  3. 定义实体:创建实体引用,以简化文档编写或引入外部资源。
  4. 定义文档结构:规定元素的层次结构,包括元素是否必须出现、可以出现多少次、以及它们之间如何嵌套。

二、DTD的基本语法

1. 定义元素
  • <!ELEMENT 元素名 (子元素内容)>:定义一个元素及其内容模型。
    • EMPTY:表示该元素没有内容,只能有属性。
    • #PCDATA:表示该元素包含的是字符数据(Parsed Character Data)。
    • (元素1, 元素2, ...):表示元素1、元素2等按顺序出现。
    • (元素1 | 元素2 | ...):表示可以选择元素1或元素2等中的一个。
    • 元素?:表示该元素是可选的,最多出现一次。
    • 元素*:表示该元素可以出现零次或多次。
    • 元素+:表示该元素至少出现一次,可以出现多次。
2. 定义属性
  • <!ATTLIST 元素名 属性名 类型 默认值>:为元素定义属性。
    • 类型
      • CDATA:字符数据,可以包含任何文本。
      • ID:唯一标识符,必须是唯一的。
      • IDREF:引用一个ID类型的属性值。
      • IDREFS:多个ID引用,用空格分隔。
      • ENTITY:实体引用。
      • ENTITIES:多个实体引用,用空格分隔。
      • NMTOKEN:名称标记,由字母、数字、连字符、下划线等组成。
      • NMTOKENS:多个名称标记,用空格分隔。
      • NOTATION:符号,用于关联外部二进制数据。
    • 默认值
      • #REQUIRED:属性是必需的。
      • #IMPLIED:属性是可选的,且没有默认值。
      • 固定值:提供一个默认值,如果未指定则使用该值。
3. 定义实体
  • 内部实体
    • <!ENTITY 实体名 "实体值">:定义一个内部实体,通常用于替换文本。
  • 外部实体
    • <!ENTITY 实体名 SYSTEM "URI">:定义一个外部实体,指向一个外部文件或资源。
    • <!ENTITY % 实体名 SYSTEM "URI">:定义一个参数实体,只能在DTD中使用。
4. 定义符号
  • <!NOTATION 符号名 SYSTEM "URI">:定义一个符号,用于关联外部二进制数据,例如图像或音频文件。

三、DTD的应用

1. 内部DTD

将DTD直接写入XML文档的头部,适用于小型文档或简单的结构定义。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [<!ELEMENT note (to, from, heading, body)><!ELEMENT to (#PCDATA)><!ELEMENT from (#PCDATA)><!ELEMENT heading (#PCDATA)><!ELEMENT body (#PCDATA)>
]>
<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body>
</note>
2. 外部DTD

将DTD保存在一个单独的文件中,并在XML文档中引用。适用于大型项目或需要共享DTD的情况。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body>
</note>

四、DTD的优点与局限性

优点
  • 简单易用:语法相对简单,容易学习和使用。
  • 广泛支持:几乎所有XML解析器都支持DTD。
  • 兼容性好:DTD是最早的XML约束机制,具有良好的向后兼容性。
局限性
  • 功能有限:相比XSD(XML Schema Definition),DTD的功能较为有限,无法定义复杂的数据类型和约束。
  • 不支持命名空间:DTD不支持XML命名空间,这在现代XML应用中是一个重要的限制。
  • 难以维护:对于复杂的文档结构,DTD可能会变得难以维护和扩展。

五、总结

DTD作为一种早期的XML约束机制,虽然简单易用,但在现代XML应用中逐渐被更强大的XSD所取代。尽管如此,了解DTD的基本概念和语法仍然是非常有价值的,尤其是在处理遗留系统或简单XML文档时。如果你需要更强大的约束和更灵活的定义,建议考虑使用XSD或其他现代的XML验证技术。

规定里面写哪些标签,标签的顺序

在mapper接口不能重载,因为在xml文件中无法映射

工厂模式学!!假期

这段代码是一个使用MyBatis框架进行数据库操作的测试类,它展示了如何通过MyBatis执行一个简单的查询操作。下面是对代码的详细解释:

1. 包声明和导入

package com.atguigu.test;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
  • package com.atguigu.test;:指定了这个类所在的包名。
  • import语句:导入了必要的类和接口,包括MyBatis的核心类(如ResourcesSqlSessionSqlSessionFactorySqlSessionFactoryBuilder)以及JUnit的测试注解@Test

2. 测试方法 testSelectEmployee

@Test
public void testSelectEmployee() throws IOException {
  • @Test:这是一个JUnit注解,表明该方法是一个测试方法。
  • throws IOException:表示该方法可能会抛出IOException异常,这通常是因为读取配置文件时可能出现的I/O错误。

3. 创建 SqlSessionFactory 对象

// 1.创建SqlSessionFactory对象
String mybatisConfigFilePath = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • String mybatisConfigFilePath = "mybatis-config.xml";:声明了MyBatis全局配置文件的路径。mybatis-config.xml 是MyBatis的配置文件,包含了数据库连接信息、事务管理、映射文件的位置等配置。
  • InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);:使用 Resources.getResourceAsStream 方法以输入流的形式加载MyBatis配置文件。Resources 类是MyBatis提供的工具类,用于加载资源文件。
  • SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);:基于读取的MyBatis配置文件的输入流,使用 SqlSessionFactoryBuilder 构建 SqlSessionFactory 对象。SqlSessionFactory 是一个工厂类,用于创建 SqlSession 对象。

4. 开启 SqlSession 会话

// 2.使用SqlSessionFactory对象开启一个会话
SqlSession session = sessionFactory.openSession();
  • SqlSession session = sessionFactory.openSession();:通过 SqlSessionFactory 的 openSession() 方法开启一个新的 SqlSession 会话。SqlSession 是MyBatis的核心接口,提供了与数据库交互的方法,如执行SQL语句、管理事务等。

5. 获取 Mapper 接口类型的对象

// 3.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象(动态代理技术)
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
  • EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);:使用 SqlSession 的 getMapper() 方法获取 EmployeeMapper 接口的实现对象。EmployeeMapper 是一个用户定义的接口,其中包含了一系列与 Employee 表相关的CRUD操作方法。MyBatis使用动态代理技术为这些接口生成实现类,使得你可以像调用普通Java方法一样调用这些方法来执行SQL语句。

6. 执行查询操作

// 4. 调用代理类方法既可以触发对应的SQL语句
Employee employee = employeeMapper.selectEmployee(1);
System.out.println("employee = " + employee);
  • Employee employee = employeeMapper.selectEmployee(1);:调用 EmployeeMapper 接口中的 selectEmployee 方法,传入参数 1,表示查询ID为1的员工记录。MyBatis会根据 EmployeeMapper 接口中的方法签名和参数,找到对应的SQL语句并执行查询操作。
  • System.out.println("employee = " + employee);:将查询到的员工对象打印到控制台。

7. 提交事务和关闭会话

// 4.关闭SqlSession
session.commit(); //提交事务 [DQL不需要,其他需要]
session.close(); //关闭会话
  • session.commit();:提交事务。对于查询操作(DQL),提交事务不是必须的,但对于插入、更新、删除操作(DML),提交事务是必要的,以确保更改被保存到数据库中。
  • session.close();:关闭 SqlSession 会话,释放资源。这是非常重要的一步,确保数据库连接和其他资源能够及时回收。

8. 完整代码

package com.atguigu.test;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;public class MyBatisTest {@Testpublic void testSelectEmployee() throws IOException {// 1.创建SqlSessionFactory对象String mybatisConfigFilePath = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 2.使用SqlSessionFactory对象开启一个会话SqlSession session = sessionFactory.openSession();try {// 3.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象(动态代理技术)EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);// 4. 调用代理类方法既可以触发对应的SQL语句Employee employee = employeeMapper.selectEmployee(1);System.out.println("employee = " + employee);// 5. 提交事务 (对于查询操作,提交事务不是必须的)session.commit();} finally {// 6. 关闭SqlSessionsession.close();}}
}

9. 改进建议

  • 使用 try-with-resources:为了确保 SqlSession 在任何情况下都能正确关闭,可以使用 try-with-resources 语句,这样即使发生异常,SqlSession 也会自动关闭。
@Test
public void testSelectEmployee() throws IOException {String mybatisConfigFilePath = "mybatis-config.xml";try (InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);SqlSession session = new SqlSessionFactoryBuilder().build(inputStream).openSession()) {EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);Employee employee = employeeMapper.selectEmployee(1);System.out.println("employee = " + employee);// 对于查询操作,提交事务不是必须的session.commit();}
}
  • 异常处理:可以在 catch 块中添加更详细的异常处理逻辑,例如记录日志或重新抛出异常。

总结

这段代码展示了如何使用MyBatis进行数据库查询操作的基本流程,包括创建 SqlSessionFactory、开启 SqlSession、获取 Mapper 接口的实现对象、执行SQL语句、提交事务和关闭会话。通过这种方式,你可以轻松地在Java应用程序中集成MyBatis,并利用其强大的功能进行数据库操作。

MyBatis是一个框架,使用不一定简单,功能强大,性能优异

SqlSessionFactory是全局应该保留的一个对象

使用ibatis方式进行数据库调用

返回值类型需要自己指定

sqlSessionFactory就会缓存mybatis的一些配置

这张图展示了MyBatis(原名为iBatis)的工作流程和组件之间的关系。下面是对图中各个部分的详细解释:

1. SqlSessionFactory

  • SqlSessionFactory 是一个工厂类,用于创建 SqlSession 对象。它包含了数据库连接信息和配置信息。
  • 数据库信息:包括数据库的URL、用户名、密码等连接信息。
  • 功能开关:配置MyBatis的各种功能开关,如缓存、事务管理等。
  • map:一个映射表,存储了所有命名空间和SQL语句的映射关系。

2. mybatis-config.xml

  • mybatis-config.xml 是MyBatis的全局配置文件,包含了数据库连接信息、事务管理、映射文件的位置等配置。
  • 数据库信息:配置数据库连接的URL、用户名、密码等。
  • 功能开关:配置MyBatis的各种功能开关。
  • 指定mapper.xml文件:配置映射文件的位置,通过 <mapper> 标签指定。

3. xxxxMapper.xml

  • xxxxMapper.xml 是映射文件,包含了具体的SQL语句和映射规则。
  • namespace:命名空间,用于唯一标识映射文件中的SQL语句。
  • SQL语句
    • <select>:用于查询操作。
    • <insert>:用于插入操作。
    • <delete>:用于删除操作。
    • <update>:用于更新操作。
    • id:SQL语句的唯一标识符。
    • sql:具体的SQL语句。

4. SqlSession

  • SqlSession 是一个会话对象,用于执行SQL语句和管理事务。
  • 创建:通过 SqlSessionFactory.openSession() 创建。
  • 执行SQL:通过 SqlSession 的方法(如 selectOneinsertupdatedelete)执行SQL语句。
  • 事务管理:可以手动管理事务(commitrollback)或使用自动提交。

5. SQL语句执行流程

  1. 获取SqlSession:通过 SqlSessionFactory.openSession() 获取 SqlSession 对象。
  2. 执行SQL
    • 查找SQL语句:通过命名空间和SQL语句的id在 SqlSession 中查找对应的SQL语句。
    • 执行SQL:通过 SqlSession 的方法执行SQL语句。
    • 参数传递:传递参数到SQL语句中。
    • 结果处理:处理查询结果或更新操作的结果。

示例代码

1. mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydatabase"/><property name="username" value="root"/><property name="password" value="password"/></dataSource></environment></environments><mappers><mapper resource="com/example/mapper/UserMapper.xml"/></mappers>
</configuration>
2. UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper"><select id="selectUser" resultType="com.example.model.User">SELECT * FROM user WHERE id = #{id}</select><insert id="insertUser" parameterType="com.example.model.User">INSERT INTO user (name, email) VALUES (#{name}, #{email})</insert><update id="updateUser" parameterType="com.example.model.User">UPDATE user SET name = #{name}, email = #{email} WHERE id = #{id}</update><delete id="deleteUser">DELETE FROM user WHERE id = #{id}</delete>
</mapper>
3. Java代码
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class Main {public static void main(String[] args) {try {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();// 执行查询User user = sqlSession.selectOne("com.example.mapper.UserMapper.selectUser", 1);System.out.println(user);// 执行插入User newUser = new User();newUser.setId(2);newUser.setName("John");newUser.setEmail("john@example.com");sqlSession.insert("com.example.mapper.UserMapper.insertUser", newUser);sqlSession.commit();// 执行更新User updateUser = new User();updateUser.setId(2);updateUser.setName("Jane");updateUser.setEmail("jane@example.com");sqlSession.update("com.example.mapper.UserMapper.updateUser", updateUser);sqlSession.commit();// 执行删除sqlSession.delete("com.example.mapper.UserMapper.deleteUser", 2);sqlSession.commit();sqlSession.close();} catch (IOException e) {e.printStackTrace();}}
}

通过上述配置和代码,你可以使用MyBatis来执行各种数据库操作,并管理事务。

是全限定符

SqlSession提供了一个方法getMapper,可以根据接口生成一个代理对象



没太清楚,明天回顾一下

mapper是一个代理对象

工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个“工厂类”中,以后都使用这个工厂类来“生产”我们需要的对象。

mybatis官网怎么用,日志怎么配置

【注入攻击】就指的是web项目中登陆界面出现的随便输入正确的就可以登陆成功

DML语句返回值是int,代表影响的行数

推荐使用注解

mapper接口中不允许重载!!! 方法名重复了的话,id值就重复了

数据输入就是以上四种情形

自动装箱和拆箱复习!!

Mapper文件只负责写SQL语句,具体的配置信息全部放在mybatis-config.xml

查询,返回单个实体类型,要求列名和属性名要一致!这样才可以进行实体类的属性映射!

mybatis会帮我们映射。

数据库中命名讲究蛇形式,而Java中讲究驼峰式

查询的时候,有实体类就用实体类接,没有实体类,临时用map接值

泛型(Generics)是Java编程语言中的一种特性,它允许你编写可以处理多种数据类型的代码,而不需要为每种类型都单独编写代码。通过使用泛型,你可以创建更灵活、可重用的类和方法,同时还能保持类型安全。下面我将用通俗易懂的语言来解释泛型的概念及其用途。

1. 什么是泛型?

想象一下,你有一个工具箱,里面装满了各种各样的工具,比如螺丝刀、扳手、锤子等。现在,你想设计一个通用的“工具袋”,它可以用来装任何一种工具,而不需要为每种工具都设计一个专门的袋子。这个“工具袋”就是泛型的一个比喻。

在Java中,泛型允许你定义一个类、接口或方法,使其能够处理任意类型的数据,而不需要指定具体的类型。这样,你就可以用同一个类或方法来处理不同类型的对象,提高了代码的灵活性和复用性。

2. 泛型的好处

  • 类型安全:编译器可以在编译时检查类型是否匹配,避免了运行时的类型转换错误。
  • 代码复用:你可以编写一个泛型类或方法,适用于多种类型的数据,而不需要为每种类型都编写不同的版本。
  • 消除强制类型转换:在没有泛型的情况下,你可能需要频繁地进行类型转换,这不仅繁琐,还容易出错。使用泛型后,编译器会自动处理类型转换,使代码更加简洁和安全。

3. 泛型的基本语法

3.1 定义泛型类
public class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}
  • <T>:这里的 T 是一个类型参数,表示任意类型。你可以使用其他字母或标识符来代替 T,例如 E(Element)、K(Key)、V(Value)等。通常,T 是最常用的类型参数名称,代表“Type”。
  • Box<T>:表示这是一个泛型类,T 是该类的类型参数。你可以通过指定具体的类型来创建 Box 的实例,例如 Box<String> 或 Box<Integer>
3.2 使用泛型类
public class Main {public static void main(String[] args) {// 创建一个存储字符串的盒子Box<String> stringBox = new Box<>();stringBox.setContent("Hello, World!");System.out.println(stringBox.getContent());  // 输出: Hello, World!// 创建一个存储整数的盒子Box<Integer> integerBox = new Box<>();integerBox.setContent(42);System.out.println(integerBox.getContent());  // 输出: 42}
}

在这个例子中,Box<String> 表示一个只能存储字符串的盒子,而 Box<Integer> 表示一个只能存储整数的盒子。通过使用泛型,我们可以在同一个类中处理不同类型的数据,而不需要为每种类型都编写一个单独的类。

3.3 定义泛型方法

除了泛型类,你还可以定义泛型方法。泛型方法允许你在方法级别上使用类型参数,而不需要整个类都是泛型的。

public class Util {// 定义一个泛型方法,返回两个相同类型的对象中的较大值public static <T extends Comparable<T>> T max(T a, T b) {return a.compareTo(b) > 0 ? a : b;}
}
  • <T extends Comparable<T>>:这里的 T 是一个类型参数,并且它必须实现了 Comparable<T> 接口。这意味着 T 类型的对象可以相互比较。
  • max(T a, T b):这个方法接受两个相同类型的参数,并返回其中较大的那个。
3.4 使用泛型方法
public class Main {public static void main(String[] args) {// 比较两个字符串String str1 = "apple";String str2 = "banana";System.out.println(Util.max(str1, str2));  // 输出: banana// 比较两个整数Integer num1 = 10;Integer num2 = 20;System.out.println(Util.max(num1, num2));  // 输出: 20}
}

在这个例子中,Util.max() 方法可以用于比较不同类型的对象,只要这些对象实现了 Comparable 接口。你可以比较字符串、整数、浮点数等,而不需要为每种类型都编写一个单独的方法。

4. 泛型的限制

虽然泛型非常强大,但也有一些限制:

  • 不能使用基本类型作为类型参数:泛型只能与引用类型(如 String, Integer, Double 等)一起使用,不能直接使用基本类型(如 int, double, boolean)。如果你需要使用基本类型,可以通过其对应的包装类来实现,例如 Integer 代替 int

  • 类型擦除:在Java中,泛型是通过“类型擦除”机制实现的。也就是说,在编译后的字节码中,泛型信息会被擦除,所有的泛型类型都会被替换为它们的上限类型(通常是 Object)。因此,运行时无法获取泛型的实际类型信息。例如,List<String>List<Integer> 在运行时都被视为 List

  • 不能创建泛型数组:由于类型擦除的原因,你不能创建泛型数组,例如 new T[10] 是不允许的。但是,你可以通过一些技巧来绕过这个限制,例如使用 Array.newInstance() 或者创建一个 Object[] 数组并进行类型转换。

5. 常见的泛型类和接口

Java 标准库中已经提供了许多泛型类和接口,它们可以帮助你更方便地使用泛型。以下是一些常见的例子:

  • ArrayList<T>:动态数组,可以存储任意类型的元素。
  • LinkedList<T>:双向链表,适合频繁的插入和删除操作。
  • HashMap<K, V>:键值对映射,K 表示键的类型,V 表示值的类型。
  • HashSet<T>:基于哈希表的集合,不允许重复元素。
  • Queue<T>:队列接口,支持先进先出(FIFO)的操作。

6. 泛型的高级用法

6.1 通配符(Wildcards)

有时你可能希望一个泛型类或方法能够接受多种类型的参数,而不仅仅是特定的类型。这时可以使用通配符 ? 来表示未知类型。

  • 无界通配符<?> 表示可以是任何类型。
  • 有界通配符
    • 上界通配符<? extends T> 表示可以是 T 或 T 的子类型。
    • 下界通配符<? super T> 表示可以是 T 或 T 的父类型。
示例:使用通配符
public class Main {public static void printList(List<?> list) {for (Object elem : list) {System.out.println(elem);}}public static void addNumbers(List<? super Integer> list) {list.add(1);list.add(2);list.add(3);}public static void main(String[] args) {List<String> stringList = Arrays.asList("apple", "banana");printList(stringList);  // 可以传递任何类型的列表List<Integer> intList = new ArrayList<>();addNumbers(intList);  // 可以传递 Integer 或其父类型的列表System.out.println(intList);  // 输出: [1, 2, 3]}
}
6.2 泛型方法的多重类型参数

你可以在一个方法中定义多个类型参数,以处理不同类型的组合。

public class Util {public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {return p1.getKey().equals(p2.getKey()) &&p1.getValue().equals(p2.getValue());}
}class Pair<K, V> {private K key;private V value;public Pair(K key, V value) {this.key = key;this.value = value;}public K getKey() { return key; }public V getValue() { return value; }
}

7. 总结

泛型是Java中非常强大的特性,它允许你编写更加灵活和可重用的代码,同时保持类型安全。通过使用泛型,你可以避免大量的类型转换,减少错误的发生,并提高代码的可读性和维护性。

不用指定它的集合类型,指定泛型就行了

泛型与 resultType

在MyBatis中,resultType 用于指定查询结果的类型。对于集合类型(如 List),你只需要指定泛型即可,MyBatis 会自动处理集合的封装。

  • resultType="string": 指定返回结果为字符串类型。
  • resultType="employee": 指定返回结果为 Employee 类型的对象。

集合类型: 对于集合类型(如 List),只需要指定泛型即可,MyBatis 会自动处理集合的封装。

主键回显

如何使用mybatis插入并且返回自增长的主键或者用mybatis帮我们维护主键

DML不提交事务不更新数据库

它是自动开启事务,手动提交事务

keyColumn是从数据库中哪个列捞值,而keyProperty就是将捞出来的主键值映射到实体类的属性名

resultMap标签,自定义映射关系,可以深层次可以单层次!!

Lombo可以简化实体类的使用,@Data-》get set toString

<insert id="insert" >insert into user (username,password) values (#{username},#{password})
</insert>

主键回显是在插入语句中的

resultMap=“自定义结果”,在多表中用的更多

多表查询

连接查询复习!!!

多表关系(双向查看)

实体类设计(单向查看)

对一:包含对方的一个对象

对多:包含对方类型集合属性即可

对多的时候,为什么主键列要用id标签映射呢,最终它会去重复

多张表查询就是无限嵌套

JDBC(Java Database Connectivity,Java数据库连接)是Java编程语言中用于执行SQL语句的一个API。它为Java应用程序提供了与各种关系型数据库进行交互的能力。通过JDBC,你可以执行查询、更新、删除等操作,并且可以处理结果集。JDBC的设计目标是让开发者能够以一种统一的方式访问不同的数据库,而不需要为每个数据库编写特定的代码。

下面我将用通俗易懂的语言来解释JDBC的基本概念、工作原理、以及如何使用JDBC来连接和操作数据库。

1. 什么是JDBC?

想象一下,你有一个银行账户,想要通过手机银行应用来查看余额、转账或支付账单。为了实现这些功能,手机应用需要与银行的服务器进行通信。类似地,JDBC就是Java程序与数据库之间的“通信桥梁”。它允许Java程序向数据库发送SQL命令,并接收数据库返回的结果。

2. JDBC的工作流程

JDBC的工作流程可以分为以下几个步骤:

  1. 加载驱动程序:首先,你需要加载一个特定于数据库的JDBC驱动程序。这个驱动程序就像是Java程序与数据库之间的翻译器,负责将Java的请求转换为数据库能够理解的格式。

  2. 建立连接:加载驱动程序后,你需要通过JDBC URL、用户名和密码来建立与数据库的连接。这就像你登录银行应用时输入账号和密码一样。

  3. 创建Statement对象:一旦建立了连接,你就可以创建一个 Statement 对象(或 PreparedStatement),用于执行SQL语句。Statement 是执行SQL命令的工具,类似于你在银行应用中点击“转账”按钮。

  4. 执行SQL语句:通过 Statement 对象,你可以执行SQL查询、插入、更新或删除操作。这一步骤类似于你提交转账请求或查询余额。

  5. 处理结果集:如果你执行的是查询操作,数据库会返回一个 ResultSet 对象,其中包含了查询结果。你可以遍历这个结果集,逐行读取数据。这类似于你在银行应用中查看交易记录。

  6. 关闭资源:最后,当所有操作完成后,你需要关闭 ResultSetStatementConnection 等资源。这是非常重要的一步,因为如果不关闭这些资源,可能会导致内存泄漏或数据库连接耗尽。

3. JDBC的核心组件

JDBC API 提供了几个核心接口和类,帮助你与数据库进行交互。以下是最重要的几个:

3.1 DriverManager

DriverManager 是JDBC的核心类之一,负责管理JDBC驱动程序并建立数据库连接。你可以通过 DriverManager.getConnection() 方法来获取一个 Connection 对象。

3.2 Connection

Connection 表示与数据库的连接。它是所有数据库操作的基础,所有的 StatementPreparedStatement 都是从 Connection 中创建的。

3.3 Statement

Statement 用于执行静态的SQL语句。你可以通过 Statement 对象执行查询、插入、更新或删除操作。对于简单的SQL语句,Statement 是一个不错的选择。

3.4 PreparedStatement

PreparedStatementStatement 的子类,用于执行预编译的SQL语句。预编译的SQL语句可以包含占位符(?),你可以在执行前为这些占位符设置具体的值。PreparedStatementStatement 更安全,因为它可以防止SQL注入攻击,并且性能更好。

3.5 ResultSet

ResultSet 用于存储查询结果。它是一个表格形式的数据集,每一行代表一条记录,每一列代表一个字段。你可以通过 ResultSet 对象逐行读取查询结果。

4. JDBC的典型使用场景

4.1 查询操作

假设你想从数据库中查询所有员工的信息。你可以使用 StatementPreparedStatement 来执行查询操作,并通过 ResultSet 处理查询结果。

import java.sql.*;public class JdbcExample {public static void main(String[] args) {// 1. 加载驱动程序(现代JDBC版本通常不需要显式加载)try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT * FROM employees")) {// 2. 处理结果集while (rs.next()) {int id = rs.getInt("id");String name = rs.getString("name");double salary = rs.getDouble("salary");System.out.println("ID: " + id + ", Name: " + name + ", Salary: " + salary);}} catch (SQLException e) {e.printStackTrace();}}
}
4.2 插入操作

假设你想向数据库中插入一条新的员工记录。你可以使用 PreparedStatement 来执行插入操作,并为占位符设置具体的值。

import java.sql.*;public class JdbcInsertExample {public static void main(String[] args) {String sql = "INSERT INTO employees (name, salary) VALUES (?, ?)";try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");PreparedStatement pstmt = conn.prepareStatement(sql)) {// 1. 设置参数pstmt.setString(1, "John Doe");pstmt.setDouble(2, 70000.0);// 2. 执行插入操作int rowsAffected = pstmt.executeUpdate();System.out.println("Rows affected: " + rowsAffected);} catch (SQLException e) {e.printStackTrace();}}
}
4.3 更新操作

假设你想更新某个员工的工资。你可以使用 PreparedStatement 来执行更新操作,并为占位符设置具体的值。

import java.sql.*;public class JdbcUpdateExample {public static void main(String[] args) {String sql = "UPDATE employees SET salary = ? WHERE id = ?";try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");PreparedStatement pstmt = conn.prepareStatement(sql)) {// 1. 设置参数pstmt.setDouble(1, 75000.0);pstmt.setInt(2, 1);// 2. 执行更新操作int rowsAffected = pstmt.executeUpdate();System.out.println("Rows affected: " + rowsAffected);} catch (SQLException e) {e.printStackTrace();}}
}
4.4 删除操作

假设你想删除某个员工的记录。你可以使用 PreparedStatement 来执行删除操作,并为占位符设置具体的值。

import java.sql.*;public class JdbcDeleteExample {public static void main(String[] args) {String sql = "DELETE FROM employees WHERE id = ?";try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");PreparedStatement pstmt = conn.prepareStatement(sql)) {// 1. 设置参数pstmt.setInt(1, 1);// 2. 执行删除操作int rowsAffected = pstmt.executeUpdate();System.out.println("Rows affected: " + rowsAffected);} catch (SQLException e) {e.printStackTrace();}}
}

5. JDBC的最佳实践

5.1 使用 try-with-resources

在JDBC中,ConnectionStatementResultSet 都是需要手动关闭的资源。如果不关闭这些资源,可能会导致内存泄漏或数据库连接耗尽。为了避免这些问题,Java 7引入了 try-with-resources 语法,它会在代码块结束时自动关闭资源。

try (Connection conn = DriverManager.getConnection(url, username, password);PreparedStatement pstmt = conn.prepareStatement(sql);ResultSet rs = pstmt.executeQuery()) {// 处理结果集
} catch (SQLException e) {e.printStackTrace();
}
5.2 使用 PreparedStatement 防止SQL注入

PreparedStatement 不仅可以提高性能,还可以防止SQL注入攻击。SQL注入是一种常见的安全漏洞,攻击者可以通过在SQL语句中插入恶意代码来破坏数据库。通过使用 PreparedStatement,你可以确保传入的参数不会被解释为SQL代码。

5.3 使用连接池

每次建立数据库连接都需要消耗一定的资源和时间。如果你的应用程序频繁地与数据库交互,建议使用连接池来管理数据库连接。连接池会在应用程序启动时预先创建一定数量的连接,并在需要时将其分配给应用程序。这样可以大大提高性能,减少连接建立的时间。

常用的连接池库包括:

  • HikariCP
  • C3P0
  • DBCP
5.4 使用事务管理

在某些情况下,你可能需要确保多个SQL操作要么全部成功,要么全部失败。这时可以使用事务管理。通过 Connection 对象的 setAutoCommit(false) 方法,你可以关闭自动提交模式,并手动控制事务的提交和回滚。

try (Connection conn = DriverManager.getConnection(url, username, password)) {conn.setAutoCommit(false);  // 关闭自动提交// 执行多个SQL操作try (PreparedStatement pstmt1 = conn.prepareStatement("INSERT INTO ...");PreparedStatement pstmt2 = conn.prepareStatement("UPDATE ...")) {pstmt1.executeUpdate();pstmt2.executeUpdate();conn.commit();  // 提交事务} catch (SQLException e) {conn.rollback();  // 回滚事务throw e;}
} catch (SQLException e) {e.printStackTrace();
}

6. JDBC的常见问题及解决方案

6.1 连接超时

如果你遇到连接超时的问题,可能是由于网络问题或数据库服务器负载过高。你可以尝试增加连接超时时间,或者检查数据库服务器的状态。

Properties props = new Properties();
props.setProperty("user", "username");
props.setProperty("password", "password");
props.setProperty("connectTimeout", "30");  // 设置连接超时时间为30秒
Connection conn = DriverManager.getConnection(url, props);
6.2 SQL语法错误

如果你在执行SQL语句时遇到语法错误,首先要检查SQL语句是否正确。你可以将SQL语句复制到数据库管理工具(如MySQL Workbench、pgAdmin)中进行测试。

6.3 性能问题

如果你的应用程序性能不佳,可能是由于频繁的数据库连接或SQL查询效率低下。你可以考虑使用连接池、索引优化、批量操作等方式来提高性能。

7. 总结

JDBC是Java程序与数据库之间的重要桥梁,它提供了一种标准的方式来执行SQL语句并处理结果集。通过JDBC,你可以轻松地与各种关系型数据库进行交互,执行查询、插入、更新和删除操作。为了确保代码的安全性和性能,建议使用 PreparedStatement 防止SQL注入,使用连接池管理数据库连接,并合理使用事务管理。

离谱了到现在还具体不清楚什么是api

mybatis通过在mapper.xml文件中的标签实现动态sql语句的简化

超文本标记语言 

更新的时候至少要保证一个满足

trim标签:自定义的指定前缀以及去掉部分后缀

能替代where和set标签使用

用遍历项.属性  不能直接写属性名

也可以直接遍历语句

如果一个标签涉及多个语句!需要设置允许指定多语句!

sql片段相当于sql语句的提取

推荐方案2   方案一还得修改pom文件

在resources下创建多层包用的是斜杆或者是分开点几次

DML(Data Manipulation Language,数据操纵语言)是SQL(Structured Query Language,结构化查询语言)的一部分,用于对数据库中的数据进行操作。DML 主要包括插入、更新和删除数据的命令,以及查询数据的 SELECT 语句。虽然 SELECT 语句通常被归类为 DQL(Data Query Language,数据查询语言),但在实际应用中,它经常与 DML 一起讨论。SELECT 语句虽然通常被归类为 DQL,但在 DML 操作中也非常常用,尤其是在需要查询数据或与其他表关联时。

连接查询的复习(左右连接?)

可以CTRL单击在mybatis-config.xml中的configuration,里面有标签的顺序

  注意不能将两条查询装到一个分页区

mybatis就是ORM思维的一个框架

还有很多小一点的细节,静待复习 qwq

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/64194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

观测云亮相 Doris Summit,展示流式聚合创新技术

01 技术亮点&#xff1a;重新定义流式聚合的效率与体验 在演讲中&#xff0c;熊豹详细介绍了 GuanceDB 如何支撑观测云的全量业务场景&#xff0c;并分享了 SelectDB 在处理复杂查询中的应用与挑战。从动态表结构管理到函数下推优化&#xff0c;观测云通过灵活的架构设计有效解…

qt中tr的使用

在 Qt 中使用 tr 函数对字符串进行翻译时&#xff0c;通常会通过 Qt Linguist 工具来处理翻译。以下是一个基本的步骤说明&#xff0c;展示如何将 QPushButton *btnnew QPushButton(tr("Hello World"),this); 翻译成其他语言&#xff0c;比如中文&#xff1a; 1.创建…

基于X410的LabVIEW FPGA跳频通信系统开发

跳频通信系统是一种高效的无线通信技术&#xff0c;通过在多个频率间快速切换&#xff0c;提高抗干扰能力和信号安全性。以NI USRP X410为硬件平台&#xff0c;利用LabVIEW FPGA实现一个实时跳频通信系统&#xff0c;涵盖信号生成、触发控制、接收检测及实时数据处理。 系统架构…

校园交友app/校园资源共享小程序/校园圈子集合二手物品交易论坛、交友等综合型生活服务社交论坛

多客校园社交圈子系统搭建 校园交友多功能系统源码: 1、更改学校为独立的模块。整体UI改为绿色&#xff0c;青春色&#xff0c;更贴近校园风格。2、圈子归纳到学校去进行运营。每个学校可建立多个圈子。和其他学校圈子互不干扰。3、增加用户绑定学校&#xff0c;以后进入将默认…

医院跌倒检测识别 使用YOLO,COCO ,VOC格式对4806张原始图片进行标注,可识别病人跌倒,病人的危险行为,病床等场景,预测准确率可达96.7%

医院跌倒检测识别 使用YOLO,COCO ,VOC格式对4806张原始图片进行标注&#xff0c;可识别病人跌倒&#xff0c;病人的危险行为&#xff0c;病床等场景&#xff0c;预测准确率可达96.7&#xff05; 数据集分割 4806总图像数 训练组70&#xff05; 3364图片 有效集20&#…

SQL进阶技巧:如何根据工业制程参数计算良品率?

目录 0 问题描述 1 数据准备 2 问题分析 步骤1&#xff1a;确定每个生产批次的制程参数是否在合格范围内 步骤2&#xff1a;基于中间结果一计算临时良品数量 步骤3&#xff1a;计算良品率&#xff08;最终结果&#xff09; 3 小结 问题拓展&#xff1a;如果制程参数是动…

RK3568平台(内存篇)内存管理架构

一.内存管理架构 内核管理内存的基本单位page页: 物理内存被分割成相同大小的组,内核用页来表示这个组,页是内核管理内存的基本单位,尽管处理器的最小可寻址单位通常是字, 但是, 内存管理单元MMU通常以页为单位进行处理. 因此,从虚拟内存的上来看,页就是最小单位. 页帧…

WEB语义化的新探索:浅析LLMs.txt

【引】有人迷恋使用大模型生成各种有趣的内容&#xff0c; 有人沉醉于大模型相关技术的探索&#xff0c;没有对错&#xff0c;只在于你的乐趣所在。 一项名为 llms.txt 的新提案标志了一些非同寻常的东西的出现: 一个Web网站不仅为人类读者服务&#xff0c;而且为人工智能提供服…

YOLOv10改进,YOLOv10利用DLKAttention融合DCNv3、DCNv4形成全新的可变形大核注意力,并二次创新C2f结构,全网首发

理论介绍 完成本篇需要参考以下三篇文章,并已添加到YOLOv10代码中 YOLOv10改进,YOLOv10添加DCNv3可变性卷积与C2f结构融合(无需编译)YOLOv10改进,YOLOv10添加DCNv4可变性卷积(windows系统成功编译),全网最详细教程YOLOv10改进,YOLOv10添加DLKA-Attention可变形大核注意力…

信奥赛CSP-J复赛集训(bfs专题)(5):洛谷P3395:路障

信奥赛CSP-J复赛集训(bfs专题-刷题题单及题解)(5):洛谷P3395:路障 题目描述 B 君站在一个 n n n\times n n

SSM 技术驱动的垃圾分类系统,引领绿色风尚

第1章 概述 1.1 研究背景 随着现代网络技术发展&#xff0c;对于垃圾分类系统现在正处于网络发展的阶段&#xff0c;所以对它的要求也是比较严格的&#xff0c;要从这个系统的功能和用户实际需求来进行对系统制定开发的发展方式&#xff0c;依靠网络技术的的快速发展和现代通讯…

【从零开始的LeetCode-算法】1338. 数组大小减半

给你一个整数数组 arr。你可以从中选出一个整数集合&#xff0c;并删除这些整数在数组中的每次出现。 返回 至少 能删除数组中的一半整数的整数集合的最小大小。 示例 1&#xff1a; 输入&#xff1a;arr [3,3,3,3,5,5,5,2,2,7] 输出&#xff1a;2 解释&#xff1a;选择 {3,7…

【机器学习】【无监督学习——聚类】从零开始掌握聚类分析:探索数据背后的隐藏模式与应用实例

从零开始掌握聚类分析&#xff1a;探索数据背后的隐藏模式与应用实例 基本概念聚类分类聚类算法的评价指标&#xff08;1&#xff09;内部指标轮廓系数&#xff08;Silhouette Coefficient&#xff09;DB指数&#xff08;Davies-Bouldin Index&#xff09;Dunn指数 &#xff08…

git的卸载与安装

目录 一、Git的卸载 二、Git的安装 2.1.1 官网下载 2.1.2 镜像下载 ​编辑 2.2 安装 2.3 检验否安装成功 三、Git使用配置 一、Git的卸载 1.找到程序&#xff0c;卸载程序 2.找到Git&#xff0c;右键卸载 卸载完成&#xff01; 二、Git的安装 2.1.1 官网下载 网址&…

java+springboot+mysql高校社团网

项目介绍&#xff1a; 使用javaspringbootmysql开发的高校社团网&#xff0c;系统包含管理员、学生角色&#xff0c;功能如下&#xff1a; 管理员&#xff1a;登录系统&#xff1b;首页&#xff1b;用户管理&#xff1b;社团分类管理&#xff1b;社团信息管理&#xff08;社团…

Linux24.04 安装企业微信

今天工作需要把windows系统换成了linux&#xff0c;但是公司的沟通工具是企业微信。去企业微信官网看了&#xff0c;没有linux版本&#xff0c;只能想办法解决了&#xff0c;不然再换回去就太坑了。 方案 1、使用docker容器&#xff0c;2、使用deepin-wine 本人对docker不太熟…

C语言刷题

1. 题目描述 根据给出的三角形3条边a:b.c(a.b,c<100.000)&#xff0c;计算三角形的周长和面积。 输入描述: 一行&#xff0c;三角形3条边(能构成三角形)&#xff0c;中间用一个空格隔开. 输出描述: 一行&#xff0c;三角形周长和面积保留两位小数&#xff0c;中问用一个空…

React第十九章(useContext)

useContext useContext 提供了一个无需为每层组件手动添加 props&#xff0c;就能在组件树间进行数据传递的方法。设计的目的就是解决组件树间数据传递的问题。 用法 const MyThemeContext React.createContext({theme: light}); // 创建一个上下文function MyComponent() {…

【密码学】AES算法

一、AES算法介绍&#xff1a; AES&#xff08;Advanced Encryption Standard&#xff09;算法是一种广泛使用的对称密钥加密&#xff0c;由美国国家标准与技术研究院&#xff08;NIST&#xff09;于2001年发布。 AES是一种分组密码&#xff0c;支持128位、192位和256位三种不同…

AIGC---------AIGC在数字孪生中的应用

跨越虚拟与现实&#xff1a;AIGC在数字孪生中的应用 引言 近年来&#xff0c;人工智能生成内容&#xff08;AIGC&#xff0c;Artificial Intelligence Generated Content&#xff09;与数字孪生&#xff08;Digital Twin&#xff09;的结合&#xff0c;成为科技界的热点。AIGC…