在Spring Boot中,DAO是数据访问对象的缩写,它是一种设计模式用于提供对数据库操作的抽象层。通过使用DAO模式,我们可以将数据操作与业务逻辑分离,并提供一个单独的接口来执行所有的数据库操作。
在Spring Boot中,通常使用Spring Data JPA来实现DAO。Spring Data JPA是Spring Framework的子项目之一,用于简化JPA(Java Persistence API)的开发。Spring Data JPA提供了一些默认实现,如自动生成常见的SQL查询等。
要使用DAO,首先需要创建一个DAO接口并继承自Spring Data JPA提供的CrudRepository或JpaRepository接口。然后,定义该接口所代表的实体类及其主键类型。例如:
public?interface?UserRepository?extends?JpaRepository<User,?Long>?{
????//?自定义查询方法
????List<User>?findByLastName(String?lastName);
}
在上面的示例中,UserRepository是一个DAO接口,其中User是实体类,Long是主键类型。findByLastName是一个自定义的查询方法。
最后,在Service或Controller中注入该DAO接口并调用其方法即可完成对数据库的操作。
com.example.app.dao.ILoginDao
接口已经被定义为一个Bean并被Spring容器管理了。可以通过在该接口上加上@Component
注解或者在配置文件中使用<bean>
标签来将它声明为一个bean。com.example.app.service.impl.LoginService
类已经被Spring容器管理了。可以在该类上加上@Service
注解或者在配置文件中使用<bean>
标签来将它声明为一个bean。com.example.app.service.impl.LoginService
类中,已经正确地注入了com.example.app.dao.ILoginDao
类型的bean。可以在该字段上加上@Autowired
注解或者在构造函数中进行注入。在Spring Boot中,DAO(Data Access Object)是一种设计模式,它提供了一个抽象层来访问数据库。使用DAO模式能够将数据操作与业务逻辑分离,并提供统一的接口来执行所有的数据库操作。Spring Boot通过整合Spring Data JPA和MyBatis等ORM框架来实现DAO功能。
下面是一个使用Spring Data JPA实现DAO的示例:
1.创建一个实体类User,用来映射数据库表的字段:
@Entity
@Table(name?=?"users")
public?class?User?{
????@Id
????@GeneratedValue(strategy?=?GenerationType.IDENTITY)
????private?Long?id;
????@Column(nullable?=?false,?unique?=?true)
????private?String?username;
????@Column(nullable?=?false)
????private?String?password;
????@Column(nullable?=?false)
????private?String?email;
????//?getters?and?setters
}
2.创建一个继承自JpaRepository
的接口UserRepository
,用于定义User实体的数据访问接口:
@Repository
public?interface?UserRepository?extends?JpaRepository<User,?Long>?{
????Optional<User>?findByUsername(String?username);
????Boolean?existsByUsername(String?username);
????Boolean?existsByEmail(String?email);
}
3.在Service层中使用UserRepository
:
@Service
public?class?UserService?{
????@Autowired
????private?UserRepository?userRepository;
????public?User?getUserById(Long?id)?{
????????return?userRepository.findById(id).orElseThrow(()?->?new?RuntimeException("User?not?found"));
????}
????public?User?saveUser(User?user)?{
????????return?userRepository.save(user);
????}
????public?void?deleteUser(Long?userId)?{
????????userRepository.deleteById(userId);
????}
}
在这个示例中,UserService
类注入了一个UserRepository
的实例,并使用内置的方法来实现对用户数据的增删改查操作。
4.在Controller层中调用UserService
:
@RestController
@RequestMapping("/api/users")
public?class?UserController?{
????@Autowired
????private?UserService?userService;
????@GetMapping("/{id}")
????public?ResponseEntity<User>?getUserById(@PathVariable?Long?id)?{
????????User?user?=?userService.getUserById(id);
????????return?ResponseEntity.ok(user);
????}
????@PostMapping
????public?ResponseEntity<User>?createUser(@RequestBody?User?user)?{
????????User?savedUser?=?userService.saveUser(user);
????????return?ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
????}
????@DeleteMapping("/{id}")
????public?ResponseEntity<Void>?deleteUser(@PathVariable?Long?id)?{
????????userService.deleteUser(id);
????????return?ResponseEntity.noContent().build();
????}
}
在这个示例中,UserController
通过注入UserService
实例来访问和操作用户数据。其中,@GetMapping
、@PostMapping
和@DeleteMapping
注解分别对应HTTP GET、POST和DELETE请求,Spring Boot会自动将JSON格式的请求体解析成Java对象。
综上所述,使用DAO模式可以将数据操作与业务逻辑分离,并提供统一的接口来执行所有的数据库操作。在Spring Boot中,我们可以使用ORM框架(如Spring Data JPA和MyBatis)来实现DAO功能。
<beans?xmlns="http://www.springframework.org/schema/beans"
???????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???????xsi:schemaLocation="http://www.springframework.org/schema/beans
????????http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
????<bean?id="loginDao"?class="com.example.app.dao.LoginDaoImpl"/>
</beans>
@Autowired(required=true)
注解表示该属性必须在Spring容器中找到对应的bean进行注入,如果找不到就会抛出异常。如果想要取消这个强制依赖关系,可以将required
属性设置为false
。
DefaultResultSetHandler.instantiateCollectionPropertyIfAppropriate()
是 MyBatis 中用于实例化集合类型属性的方法。当查询语句返回多条记录时,MyBatis 会调用该方法将结果集封装到一个集合对象中,以便后续处理。
具体来说,该方法首先会检查传入参数 resultContext
是否包含集合类型属性,并且该属性为 null 或空集合。如果是,则会通过反射创建一个新的集合对象,并将其赋值给对应的属性。这个集合对象的类型由 resultMap
中定义的集合类型指定。如果 resultMap
中没有指定集合类型,则默认使用 java.util.ArrayList
。
需要注意的是,该方法仅在 resultType
为集合类型(例如 List
、Set
等)时才会被调用。如果 resultType
是其他类型(如自定义 Java 对象),则不会调用该方法。
假设我们有一个 User
类,其中包含一个名为 orders
的属性,表示用户的订单列表:
public?class?User?{
????private?Integer?id;
????private?String?name;
????private?List<Order>?orders;
????//?getters?and?setters
}
public?class?Order?{
????private?Integer?id;
????private?String?product;
????private?Integer?quantity;
????//?getters?and?setters
}
在 MyBatis 中,我们可以编写如下的查询语句来查询用户及其订单:
<select?id="getUserWithOrders"?resultMap="userResultMap">
????SELECT?u.*,?o.id?AS?order_id,?o.product,?o.quantity
????FROM?user?u
????LEFT?JOIN?order?o?ON?u.id?=?o.user_id
????WHERE?u.id?=?#{id}
</select>
这里使用了 LEFT JOIN
来将用户和订单关联起来,查询结果中可能包含多条记录。在对这个查询结果进行映射时,MyBatis 会通过以下步骤处理集合类型属性 orders
:
userResultMap
中,我们需要使用 <collection>
元素来指定如何映射 orders
属性:<resultMap?id="userResultMap"?type="User">
????<id?property="id"?column="id"/>
????<result?property="name"?column="name"/>
????<collection?property="orders"?ofType="Order">
????????<id?property="id"?column="order_id"/>
????????<result?property="product"?column="product"/>
????????<result?property="quantity"?column="quantity"/>
????</collection>
</resultMap>
"Initializing Spring DispatcherServlet 'dispatcherServlet'"是Spring框架在启动时输出的日志信息之一。它表示正在初始化Spring MVC中的DispatcherServlet,即Web请求的入口点。
DispatcherServlet是Spring MVC模式中的核心组件之一。它负责接收来自客户端的HTTP请求,并将请求分派到合适的控制器(Controller)进行处理。在Spring框架中,可以通过配置多个DispatcherServlet实例来处理不同URL模式的请求。
注解 @SpringBootApplication
用于启动Spring Boot应用程序、@MapperScan("com.example.app.dao")
用于扫描Mybatis Mapper接口并生成代理对象、@ImportResource("classpath:applicationContext.xml")
用于加载XML配置文件。
另外,该类还继承了 SpringBootServletInitializer
并重写了它的 configure()
方法,这表明正在使用 WAR 部署方式来部署的应用程序。
在MyBatis框架中,@MapperScan("com.example.app.dao")
和@MapperScan("com.example.app.mapper")
注解的作用是扫描指定包下的Java接口,将其注册为MyBatis的Mapper接口。
通常情况下,这两个注解没有本质上的区别,只是命名不同而已。开发者可以根据自己的实际业务需求来选择更加合适的命名方式,以方便阅读和维护代码。
需要注意的是,使用时应该确保注解中的包路径与Mapper接口所在的包路径相匹配,否则可能会导致Mapper接口无法被正确扫描和注册。
将 com.example.app.entity.Login 类型的对象强制转换为 com.alibaba.fastjson.JSONObject 类型,但是这两个类不能直接互相转换导致了异常。
要修复这个问题,需要检查代码中涉及到这两个类的部分,看看是否错误地进行了类型转换或者使用了错误的数据类型。可能需要修改代码以确保正确的类型转换才能够顺利执行。
仓库地址:https://github.com/webVueBlog/JavaGuideInterview