mybatis是一个持久层框架,针对的是JDBC的优化
简化数据库操作,能进行单表、多表操作,在这个框架下,需要我们自己写SQL语句
Mapper接口和MapperXML文件就相当于Dao和Dao层的实现

通常将xml文件放在resources包下 ,放在Java文件maven不会打包
DTD(Document Type Definition,文档类型定义)是一种用于定义XML文档结构和内容规则的技术。它描述了允许的元素、属性、实体以及它们之间的关系,从而确保XML文档遵循特定的格式。DTD可以内嵌在XML文档中,也可以作为外部文件引用。以下是关于DTD约束的一些关键点:
一、DTD的作用
- 定义元素:指定哪些元素可以在文档中出现,以及这些元素可以包含什么内容。
- 定义属性:为元素定义可能的属性及其值的类型(如CDATA、ID、IDREF等)。
- 定义实体:创建实体引用,以简化文档编写或引入外部资源。
- 定义文档结构:规定元素的层次结构,包括元素是否必须出现、可以出现多少次、以及它们之间如何嵌套。
二、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的核心类(如Resources,SqlSession,SqlSessionFactory,SqlSessionFactoryBuilder)以及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的方法(如selectOne、insert、update、delete)执行SQL语句。- 事务管理:可以手动管理事务(
commit、rollback)或使用自动提交。5. SQL语句执行流程
- 获取SqlSession:通过
SqlSessionFactory.openSession()获取SqlSession对象。- 执行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的工作流程可以分为以下几个步骤:
加载驱动程序:首先,你需要加载一个特定于数据库的JDBC驱动程序。这个驱动程序就像是Java程序与数据库之间的翻译器,负责将Java的请求转换为数据库能够理解的格式。
建立连接:加载驱动程序后,你需要通过JDBC URL、用户名和密码来建立与数据库的连接。这就像你登录银行应用时输入账号和密码一样。
创建Statement对象:一旦建立了连接,你就可以创建一个
Statement对象(或PreparedStatement),用于执行SQL语句。Statement是执行SQL命令的工具,类似于你在银行应用中点击“转账”按钮。执行SQL语句:通过
Statement对象,你可以执行SQL查询、插入、更新或删除操作。这一步骤类似于你提交转账请求或查询余额。处理结果集:如果你执行的是查询操作,数据库会返回一个
ResultSet对象,其中包含了查询结果。你可以遍历这个结果集,逐行读取数据。这类似于你在银行应用中查看交易记录。关闭资源:最后,当所有操作完成后,你需要关闭
ResultSet、Statement和Connection等资源。这是非常重要的一步,因为如果不关闭这些资源,可能会导致内存泄漏或数据库连接耗尽。3. JDBC的核心组件
JDBC API 提供了几个核心接口和类,帮助你与数据库进行交互。以下是最重要的几个:
3.1
DriverManager
DriverManager是JDBC的核心类之一,负责管理JDBC驱动程序并建立数据库连接。你可以通过DriverManager.getConnection()方法来获取一个Connection对象。3.2
Connection
Connection表示与数据库的连接。它是所有数据库操作的基础,所有的Statement和PreparedStatement都是从Connection中创建的。3.3
Statement
Statement用于执行静态的SQL语句。你可以通过Statement对象执行查询、插入、更新或删除操作。对于简单的SQL语句,Statement是一个不错的选择。3.4
PreparedStatement
PreparedStatement是Statement的子类,用于执行预编译的SQL语句。预编译的SQL语句可以包含占位符(?),你可以在执行前为这些占位符设置具体的值。PreparedStatement比Statement更安全,因为它可以防止SQL注入攻击,并且性能更好。3.5
ResultSet
ResultSet用于存储查询结果。它是一个表格形式的数据集,每一行代表一条记录,每一列代表一个字段。你可以通过ResultSet对象逐行读取查询结果。4. JDBC的典型使用场景
4.1 查询操作
假设你想从数据库中查询所有员工的信息。你可以使用
Statement或PreparedStatement来执行查询操作,并通过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中,
Connection、Statement和ResultSet都是需要手动关闭的资源。如果不关闭这些资源,可能会导致内存泄漏或数据库连接耗尽。为了避免这些问题,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