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