框架阶段总结
framework:框架 ,根据一些编程思想, 把一些功能封装起来,帮助更好的,更快的做软件开发, 发
布为jar包, 供其他程序员使用,这样的一些软件,被称为框架, 比如spring , spring mvc , mybatis, hibernate , spring boot 等
框架阶段学习了Spring、SpringMvc、Mybatis、SpringBoot、MybatisPlus和SpringBoot-JPA框架
1.Spring
1.1Spring中的几个概念
-
IoC(Inversion of Control):控制反转,由Spring框架创建对象,管理对象和对象之间的依赖关系。 -
DI(Dependency Injection):依赖注入,在程序运行期间,IOC容器动态地将对象需要的外部资源注入到对象中使用,依赖注入的方式有构造器注入、set注入、注解输入,IoC是通过DI来实现的。 -
bean:是由Spring框架创建的对象。 -
pojo(Plain Ordinary Java Object):简单的Java类,只有私有属性和公开set/get方法等的类。 -
AOP( Aspect-Oriented Programming ):面向切面编程,是将程序中重复分散的非业务逻辑代码(如日志、事务等)进行集中的管理,在需要使用时“切入”到程序中运行,AOP可以提高代码的可重复利用性,可维护性,降低对象之间的耦合度。
1.2使用Spring框架
1.2.1导入spring mvc的jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.21</version>
</dependency>
1.2.2创建Spring框架的xml文件
通常命名为applicationContext.xml,放在resources下
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
</beans>
1.2.3定义java类,在spring的xml文件中配置bean对象
package com.xsh.entity;
public class Phone {
private String brand;
private double price;
private int memory;
}
有三种方式创建对象
- 调用构造函数
- 调用自己的静态方法
- 调用容器中的其他bean的方法,创建对象
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean id="p1" class="com.xsh.entity.Phone"></bean>
<bean id="date" class="java.util.Date"></bean>
<bean id="cal" class="java.util.Calendar" factory-method="getInstance"></bean>
<bean id="date1" class="java.util.Date" factory-bean="cal" factory-method="getTime"></bean>
</beans>
1.2.4创建Spring的容器,在容器中获取对象,使用对象
public class PhoneTest {
@Test
public void getPhone() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("ac:" + ac);
Phone p1 = ac.getBean("p1", Phone.class);
p1.setBrand("华为");
System.out.println(p1.getBrand());
System.out.println(p1.getClass());
System.out.println(Phone.class);
}
}
1.3spring的xml中初始化bean的方式及bean标签的属性
1.3.1创建对象的方式
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean id="phone" class="com.xsh.entity.Phone">
<constructor-arg name="brand" value="华为"></constructor-arg>
<constructor-arg name="price" value="200.0"></constructor-arg>
<constructor-arg name="memory" value="128"></constructor-arg>
</bean>
<bean id="phone1" class="com.xsh.entity.Phone">
<constructor-arg index="0" value="三星"></constructor-arg>
<constructor-arg index="1" value="300.0"></constructor-arg>
<constructor-arg index="2" value="256"></constructor-arg>
</bean>
<bean id="str" class="java.lang.String">
<constructor-arg index="0" value="alice"></constructor-arg>
</bean>
<bean id="person" class="com.xsh.entity.Person">
<constructor-arg name="name" ref="str"></constructor-arg>
<constructor-arg name="phone" ref="phone1"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
</bean>
<bean id="person1" class="com.xsh.entity.Person">
<property name="name" value="tom"></property>
<property name="phone" ref="phone"></property>
<property name="age" value="19"></property>
</bean>
<bean id="teacher" class="com.xsh.entity.Teacher">
<constructor-arg name="name" value="张老师"></constructor-arg>
<constructor-arg name="level" value="6"></constructor-arg>
</bean>
<bean id="cat" class="com.xsh.entity.Cat">
<constructor-arg name="name" value="团团"></constructor-arg>
<constructor-arg name="sex" value="公"></constructor-arg>
</bean>
<bean id="student" class="com.xsh.entity.Student">
<constructor-arg name="name" value="小明"></constructor-arg>
<constructor-arg name="className" value="软件一班"></constructor-arg>
<property name="teacher" ref="teacher"></property>
<property name="cat" ref="cat"></property>
</bean>
<bean id="test" class="com.xsh.entity.Phone" scope="prototype"></bean>
<bean id="test1" class="com.xsh.entity.Phone" scope="singleton"></bean>
</beans>
1.3.2bean标签的属性
<bean id="e1" class="com.xsh.entiry.ExampleBean"
init-method="init" destroy-method="destory"
scope="singleton" lazy-init="true"></bean>
初始化方法和销毁方法
<bean id="example" class="com.xsh.entity.ExampBean"
init-method="init" destroy-method="destroy" scope="singleton"></bean>
1.3.3autowired自动装配
<bean id="p1" class="com.xsh.entiry.Phone" autowire="byName">
<constructor-arg name="brand" value="华为"></constructor-arg>
</bean>
<bean id="brand" class="java.lang.String">
<constructor-arg index="0" value="华为888"></constructor-arg>
</bean>
<bean id="price" class="java.lang.Double">
<constructor-arg index="0" value="333.33"></constructor-arg>
</bean>
<bean id="mem" class="java.lang.Integer">
<constructor-arg index="0" value="128"></constructor-arg>
</bean>
<bean id="phoneShell" class="com.xsh.entiry.PhoneShell">
<property name="color" value="红色"></property>
<property name="size" value="10"></property>
</bean>
1.3.4补充:单例模式
单例模式是23种设计模式之一,指在程序运行时,一个类只存在一个实例对象
-
饿汉式单例:在该类初始化的时候就创建实例对象,线程是安全的。
class Hungry{
private static final Hungry hungry = new Hungry();
public Hungry getInstance(){
return hungry;
}
private Hungry(){
}
}
-
懒汉式单例:首次使用单例实例的时候创建,之后使用时再判断单例实例是否已创建,如果没有则创建实例,非线程安全
class Lazy{
private Lazy lazy;
public Lazy getInstance(){
if (lazy!=null){
return new Lazy();
}
return lazy;
}
private Lazy(){
}
}
1.4Spring注解的使用
1.4.1开启注解使用功能
<context:annotation-config></context:annotation-config>
1.4.2常用注解
-
@Component : 通知spring框架,创建对象 ,默认的id,就是类名首字母小写。 -
@Configuration:在spring容器中创建对象,这个注解一般用于设置一些配置内容 -
@Bean:一般在方法前面添加这个注解,spring框架会在容器中创建这个方法返回的对象 -
@Service:业务层 -
@Controller:控制层 -
@Repository:持久层 -
@Value: 对于8种特殊数据类型和String,可以使用@Value(“xx”)的方式赋值 也可以读取属性文件的值 @Value(“${key}”) -
@Resource (javax.annotation.Resource;) : 对于应用类型,可以采用自动装配的功能,让spring容器根据容器中的对象,根据情况赋值。 -
@Qualifier(bean的id ) : 为了避免spring容器根据类型查找的时候,出现多个匹配的类型,造成异 常,可以使用该注解,主动设置好需要自动装配的bean的id -
@Autowired注解,是spring框架提供的自动装配的注解。 可以byName, byType查找对象,然后自动set注入。 -
@Component(“exam”) // id ,class -
@Scope , 设置单例,非单例 -
@Lazy ,设置懒加载
1.5AOP编程
1.5.1导入aop相关的jar包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.9.4</version>
</dependency>
1.5.1抽取公共功能封装为类
package com.xsh.dao;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
@Aspect
@EnableAspectJAutoProxy
public class Login1 {
@Before("execution(public * com.xsh..*.*(..))")
public void showTime(JoinPoint joinpoint){
String methodName = joinpoint.getSignature().getName();
Date time=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
String info = sdf.format(time);
System.out.println(methodName+"方法开始执行:"+info);
}
@Around("execution(public * com.xsh.dao.*.*(..))")
public Object exeTime(ProceedingJoinPoint joinPoint) throws Throwable {
long begin = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long end =System.currentTimeMillis();
long cha=end-begin;
System.out.println(joinPoint.getSignature().getName()+":执行消耗时间"+cha+"毫秒");
return proceed;
}
@AfterReturning(value = "execution(public * com.xsh.dao.*.*(..))",returning = "obj")
public void returnVal(JoinPoint joinPoint,Object obj){
System.out.println(joinPoint.getSignature().getName()+":"+obj);
}
}
1.5.3AOP的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.xsh"></context:component-scan>
<context:annotation-config></context:annotation-config>
<aop:config>
<aop:aspect ref="login">
<aop:pointcut id="all" expression="execution(public * com.xsh.dao.*.*(..))"/>
<aop:before method="showTime" pointcut-ref="all"></aop:before>
<aop:around method="exeTime" pointcut-ref="all"></aop:around>
<aop:after-returning method="returnVal" pointcut-ref="all" returning="obj"></aop:after-returning>
</aop:aspect>
</aop:config>
</beans>
1.5.4AOP的注解
@Component
@Aspect
@EnableAspectJAutoProxy
2.spring mvc
2.1web项目
? java的web项目
-
servlet (extend HttpServlet) , 重写service方法 -
jsp , 显示servlet转发到jsp的数据 -
web.xml , 配置servlet的路径 -
servlet, jsp需要在容器中运行,比如: 把java web项目部署到tomcat中,启动tomcat之后,就可以访问web项目了。 编码效率比较低:每次都需要写servlet类,然后要做配置,请求参数需要自己获取,自己封装为对应的对象
spring mvc框架的web项目 spring框架中包含了spring webmvc模块。通常把这个模块称为spring mvc框架。 MVC: mvc是一种web软件开发常使用的软件架构。 M-model : 持久层,实体类, dao , service ,统称为model. V-View : 界面,展示数据 C-Controller :控制层, 调用业务层,转发到对应的view.
-
DispatcherServlet.java , web.xml中配置这个servlet -
Controller(程序员写对应的类) , jsp (程序员写对应的jsp文件) -
ViewResolver & jsp , (jsp的路径配置 , spring.xml配置文件做配置) -
HandlerMapping (java的Controller类型, 映射为url , spring.xm配置文件中配置),可以用注解简化配置:HandlerMapping
2.2spring mvc的使用
-
导入对应的jar包 <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.21</version>
</dependency>
-
配置web.xml文件
<servlet>
<servlet-name>mvc</servlet-name>
<servletclass>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc1.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
-
controller package com.xsh.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
public class FirstController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request ,
HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView(); // 自己创建
Map<String, Object> model = mav.getModel(); // 获取到一个map, 把需要转
发到jsp页面的数据,保存在这个map中
model.put("name" , "小红");
mav.setViewName("Hello"); // 设置要转发的jsp的名字
return mav;
}
}
-
jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${name} , 欢迎使用!
</body>
</html>
-
ViewResolver、HandlerMapping <bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="suffix" value=".jsp"></property>
<property name="prefix" value="/WEB-INF/"></property>
</bean>
<bean id="ft" class="com.xsh.controller.FirstController"></bean>
<bean id="sc" class="com.xsh.controller.SecondController"></bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="first">ft</prop>
<prop key="second">sc</prop>
</props>
</property>
</bean>
2.3spring mvc注解的使用
-
spring.xml支持springmvc注解的设置
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="com.xsh.controller">
</context:component-scan>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="suffix" value=".jsp"></property>
<property name="prefix" value="/WEB-INF/"></property>
</bean>
-
Controller中的注解
@GetMapping("/add")
public String add(){
System.out.println("getMapping......");
return "success";
}
@PostMapping("/add")
public String add1(){
System.out.println("postMapping.....");
return "success";
}
@RequestMapping("/add")
public String add2(){
System.out.println("requestMapping .....");
return "success";
}
2.4将controller中的数据转发到jsp
-
Model @RequestMapping("/query")
public String query( Model model , Integer eno ,
HttpServletRequest request){
Emp emp = new Emp();
emp.setEName("小红");
model.addAttribute("emp" , emp);
return "success";
}
-
ModelMap @RequestMapping("/query1")
public String query1(ModelMap modelMap , Integer eno){
Emp emp = new Emp();
emp.setEName("小红");
modelMap.put("emp" , emp);
return "success";
}
-
ModelAndView @RequestMapping("/query2")
public ModelAndView query2(Integer eno){
Emp emp = new Emp();
emp.setEName("小红");
ModelAndView mav = new ModelAndView();
ModelMap modelMap = mav.getModelMap();
modelMap.put("emp" , emp);
mav.setViewName("success");
return mav;
}
2.5拦截器的使用
2.5.1定义拦截器
implements HandlerInterceptor , 重写方法
package com.xsh.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginInterceptor implements HandlerInterceptor {
@Override
了, 不能访问请求了。
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) throws Exception {
System.out.println("进入拦截器了:preHandle。。。。。。。。。");
HttpSession session = request.getSession();
Object loginuser = session.getAttribute("loginuser");
if(loginuser == null){
response.sendRedirect(
request.getContextPath() +"/toLogin");
return false;
}else{
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse
response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle............");
}
}
2.5.2拦截器的配置
-
xml中配置 拦截的路径有哪些 不拦截的路径要设置例外 <mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/toLogin"/>
<mvc:exclude-mapping path="/login"/>
<mvc:exclude-mapping path="/js/**"/>
<mvc:exclude-mapping path="/html/**"/>
<bean class="com.xsh.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/emp/**"/>
<bean class="com.xsh.interceptor.RoleInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
-
java类中添加拦截器 要求:在spring mvc的配置文件中不能出现mvc:annotation-driven标签 @Configuration
@EnableWebMvc
public class MVCConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/toLogin")
.excludePathPatterns("/login")
.excludePathPatterns("/js/**")
.excludePathPatterns("/html/**");
registry.addInterceptor(new RoleInterceptor())
.addPathPatterns("/emp/**");
}
}
2.6异常处理
2.6.1局部异常处理
@ExceptionHandler(NullPointerException.class)
请求发生异常,就执行这里toException方法。
public String toException(Exception e){
e.printStackTrace();
System.out.println(e.getCause());
5.2全局异常处理
return "part";
}
2.6.2全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler
public String toException(Exception e){
e.printStackTrace();
return "global";
}
}
3.Mybatis
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几
乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置
和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式Java 对象)为数据库中的记录。
mybatis是一个数据库相关的框架,主要为了简化jdbc的操作
mybatis使用了orm,ORM是对象关系映射的英文缩写,ORM是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
3.1mybatis的使用步骤
3.1.1mybatis的jar包
数据库jar包, mybatisjar包
<dependency>
><groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId
<version>3.5.10</version>
</dependency>
3.1.2mybatis的核心配置文件
-
数据库连接的环境配置 -
日志输出的配置 -
需要加载的mapper.xml文件的配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//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.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/gamedb?serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/HeroMapper.xml"/>
</mappers>
</configuration>
3.1.3实体类和接口
package com.xsh.entity;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
@Data
@ToString
public class Hero {
private Integer id;
private String name;
private String sex;
private String position;
private Integer price;
private Date shelf_date;
}
package com.xsh.dao;
import com.xsh.entity.Hero;
import java.util.List;
public interface HeroDao {
public abstract int addHero(Hero hero);
public abstract int deleteHero(Integer id);
public abstract int updateHero(Hero hero);
public abstract List<Hero> queryAll();
}
3.1.4 mapper.xml的配置
<mappers>
<mapper resource="mapper/HeroMapper.xml"/>
</mappers>
<mappers>
<mapper resource="mapper/HeroMapper.xml"/>
</mappers>
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xsh.dao.HeroDao">
<insert id="addHero" parameterType="com.xsh.entity.Hero">
insert into hero values(null, #{name} , #{sex}
, #{position} , #{price} , #{shelf_date})
</insert>
<delete id="deleteHero">
delete from hero where id = #{id}
</delete>
<update id="updateHero" parameterType="com.xsh.entity.Hero">
update hero set `name` = #{name} , sex=#{sex},
`position` =#{position } , price=#{price} ,
shelf_date=#{shelf_date} where id=#{id}
</update>
<select id="queryAll" resultType="com.xsh.entity.Hero">
select * from hero
</select>
</mapper>
3.1.5测试mybatis的功能
package com.xsh;
import com.xsh.dao.HeroDao;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
public class AppTest
{
SqlSession sqlSession;
@Before
public void createSession() throws Exception{
String location = "mybatis-config.xml";
InputStream resourceAsStream =
Resources.getResourceAsStream(location);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(resourceAsStream);
sqlSession = sqlSessionFactory.openSession();
}
@After
public void closeAndCommit(){
sqlSession.commit();
sqlSession.close();
}
@Test
public void testQuery()
{
HeroDao dao = sqlSession.getMapper(HeroDao.class);
System.out.println("dao:" + dao.getClass());
dao.queryAll();
}
}
3.2ResultMap的使用
如果实体类的属性和表的字段名不一致,可以使用resultMap 设置实体类的属性和表的字段的对应关 系。
GoodsInfo.java
@Data
@ToString
public class GoodsInfo {
private Integer giId;
private Integer gtId;
private String giName;
private Double giPrice;
private Integer giNum;
private String giNote;
private String giImg;
}
GoodsInfoDao.java
public List<GoodsInfo> queryAll();
GoodsInfoMapper.xml
<resultMap id="GIMap" type="com.xsh.entity.GoodsInfo">
<id column="gi_id" property="giId"></id>
<result column="gt_id" property="gtId" javaType="java.lang.Integer">
</result>
<result column="gi_name" property="giName"></result>
<result column="gi_price" property="giPrice"></result>
<result column="gi_num" property="giNum"></result>
<result column="gi_note" property="giNote"></result>
<result column="gi_img" property="giImg"></result>
</resultMap>
<select id="queryAll" resultMap="GIMap">
select * from goods_info
</select>
3.3接口方法的定义
接口方法的返回值
public List<GoodsInfo> queryAll();
public GoodsInfo queryByID(Integer giId);
public Map<String , Object> queryByIDMap(Integer giId);
public int queryTotal();
public List<Map<String ,Object>> queryByGroup();
public List<GroupGoods> queryByGroupGoods();
public void addGoodsInfo(GoodsInfo info);
xml
<resultMap id="GIMap" type="com.xsh.entity.GoodsInfo">
<id column="gi_id" property="giId"></id>
<result column="gt_id" property="gtId" javaType="java.lang.Integer">
</result>
<result column="gi_name" property="giName"></result>
<result column="gi_price" property="giPrice"></result>
<result column="gi_num" property="giNum"></result>
<result column="gi_note" property="giNote"></result>
<result column="gi_img" property="giImg"></result>
</resultMap>
<select id="queryAll" resultMap="GIMap">
select * from goods_info
</select>
<select id="queryByID" resultMap="GIMap" parameterType="int">
select gi_name , gi_price , gi_num
from goods_info where gi_id= #{giId}
</select>
<select id="queryTotal" resultType="java.lang.Integer">
select count(*) from goods_info
</select>
<select id="queryByIDMap" resultType="map">
select gi_name , gi_price , gi_num
from goods_info where gi_id= #{giId}
</select>
2.2接口方法的参数
java
xml
<select id="queryByGroup" resultType="java.util.Map">
SELECT count(goods_info.gt_id) as count , SUM(gi_num) as total
, goods_info.gt_id as type,gt_name as name from goods_info , goods_type
where goods_info.gt_id = goods_type.gt_id
GROUP BY goods_info.gt_id
</select>
<select id="queryByGroupGoods" resultType="com.xsh.entity.GroupGoods">
SELECT count(goods_info.gt_id) as count , SUM(gi_num) as total
, goods_info.gt_id as type,gt_name as name from goods_info , goods_type
where goods_info.gt_id = goods_type.gt_id
GROUP BY goods_info.gt_id
</select>
<insert id="addGoodsInfo" parameterType="com.xsh.entity.GoodsInfo"
useGeneratedKeys="true" keyColumn="gi_id" keyProperty="giId">
insert into goods_info(gi_id , gt_id , gi_name , gi_price , gi_num ,
gi_note , gi_img)
values(null , #{gtId} , #{giName} , #{giPrice} ,#{giNum} , #{giNote} ,#
{giImg})
</insert>
接口方法的参数
gi_price ......);
String)
public void updateByWhere(Map map) ;
获取value值
public List<GoodsInfo> selectWhere(@Param("gid") Integer id ,
@Param("type") Integer type ,@Param("jiage") Double price );
public void delete(Integer giId);
xml
<update id="updateByWhere" parameterType="map">
update goods_info set
gi_num=#{num} where gt_id=#{type}
</update>
<select id="selectWhere" resultMap="GIMap" >
select * from goods_info where gi_id>#{gid} and gt_id=#{type}
and gi_price < #{jiage}
</select>
<delete id="delete" >
delete from goods_info where gi_id=#{giId}
</delete>
3.4动态sql语句
使用一些标签,实现sql语句可以根据条件,拼出不同的sql语句,实现不同的功能。
<update id="updateByWhere" parameterType="map">
update goods_info set
gi_num=#{num} where gt_id=#{type}
</update>
<select id="selectWhere" resultMap="GIMap" >
select * from goods_info where gi_id>#{gid} and gt_id=#{type}
and gi_price < #{jiage}
</select>
<delete id="delete" >
delete from goods_info where gi_id=#{giId}
</delete>
public interface DynamicGoodsInfoDao {
// 根据参数是否为空,动态完成sql语句的拼接
public List<GoodsInfo> findWhere(GoodsInfo info);
// 根据参数是否为空,动态完成sql语句的拼接
public List<GoodsInfo> findWhereTwo(GoodsInfo info);
public void updateSelectiveById(GoodsInfo info);
public void updateSelectiveByIdTrim(GoodsInfo info);
}
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xsh.dao.DynamicGoodsInfoDao">
<resultMap id="GIMap" type="com.xsh.entity.GoodsInfo">
<id column="gi_id" property="giId"></id>
<result column="gt_id" property="gtId" javaType="java.lang.Integer">
</result>
<result column="gi_name" property="giName"></result>
<result column="gi_price" property="giPrice"></result>
<result column="gi_num" property="giNum"></result>
<result column="gi_note" property="giNote"></result>
<result column="gi_img" property="giImg"></result>
</resultMap>
<select id="findWhere" resultMap="GIMap"
parameterType="com.xsh.entity.GoodsInfo">
select * from goods_info where 1=1
<if test="giId!=null">
and gi_id = #{giId}
</if>
<if test="gtId!=null">
and gt_id = #{gtId}
</if>
<if test="giPrice!=null">
and gi_price>#{giPrice}
</if>
<if test="giNum!=null">
and gi_num > #{giNum}
</if>
</select>
<select id="findWhereTwo" resultMap="GIMap"
parameterType="com.xsh.entity.GoodsInfo">
select * from goods_info
<where>
<if test="giId!=null">
and gi_id = #{giId}
</if>
<if test="gtId!=null">
and gt_id = #{gtId}
</if>
<if test="giPrice!=null">
and gi_price>#{giPrice}
</if>
<if test="giNum!=null">
and gi_num > #{giNum}
</if>
</where>
</select>
<update id="updateSelectiveById"
parameterType="com.xsh.entity.GoodsInfo">
update goods_info
<set>
<if test="gtId!=null">
gt_id=#{gtId} ,
</if>
<if test="giName!=null">
gi_name=#{giName} ,
</if>
<if test="giPrice!=null">
gi_price=#{giPrice} ,
</if>
<if test="giNum!=null">
gi_num=#{giNum} ,
</if>
<if test="giNote!=null">
gi_note=#{giNote} ,
</if>
<if test="giImg!=null">
gi_img=#{giImg} ,
</if>
</set>
<where>
<if test="giId!=null">
gi_id=#{giId}
</if>
</where>
</update>
<update id="updateSelectiveByIdTrim"
parameterType="com.xsh.entity.GoodsInfo">
update goods_info
<trim prefix="set" prefixOverrides="" suffix=" where gi_id=#{giId}"
suffixOverrides=",">
<if test="gtId!=null">
gt_id=#{gtId} ,
</if>
<if test="giName!=null">
gi_name=#{giName} ,
</if>
<if test="giPrice!=null">
gi_price=#{giPrice} ,
</if>
<if test="giNum!=null">
gi_num=#{giNum} ,
</if>
<if test="giNote!=null">
gi_note=#{giNote} ,
</if>
<if test="giImg!=null">
gi_img=#{giImg} ,
</if>
</trim>
</update>
</mapper>
3.5关联查询
BookInfo.java
@Data
@ToString
public class BookInfo {
private Integer bookId;
private Integer typeId;
private String bookName;
private String bookAuthor;
private Double bookPrice;
private Date bookPublishDate;
private Integer bookNum;
private BookType bookType ;
}
BookType.java
@Data
@ToString
public class BookType {
private Integer typeId;
private String typeName;
private List<BookInfo> bookInfoList;
}
mapper.java
public interface BookInfoDao {
public List<BookInfo> queryAll();
}
mapper.xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace: 命名空间 , 设置mapper.xml文件中的sql 对应的 interface。 -->
<mapper namespace="com.xsh.dao.BookInfoDao">
<resultMap id="BookInfoMap" type="com.xsh.entity.BookInfo">
<id property="bookId" column="book_id"></id>
<result property="typeId" column="type_id"></result>
<result property="bookName" column="book_name"></result>
<result property="bookAuthor" column="book_author"></result>
<result property="bookPrice" column="book_price"></result>
<result property="bookPublishDate" column="book_publish_date"></result>
<result property="bookNum" column="book_num"></result>
<!-- association : 设置关联关系对应的属性
property="bookType" : 有关联关系的属性名
javaType="com.xsh.entity.BookType" :有关联关系的属性对应的类型
-->
<association property="bookType" javaType="com.xsh.entity.BookType">
<id property="typeId" column="type_id"></id>
<result property="typeName" column="typeName"></result>
</association>
</resultMap>
<!-- public List<BookInfo> queryAll();-->
<select id="queryAll" resultMap="BookInfoMap" >
select * from bookinfo as info , book_type as type where
info.type_id = type.type_id
</select>
</mapper>
3.6分页插件的使用
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
- 在mybatis-config.xml中配置分页的插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="reasonable" value="true"/>
</plugin>
</plugins>
@Test
public void testPageHelper(){
BookInfoDao dao = sqlSession.getMapper(BookInfoDao.class);
PageHelper.startPage(2, 1) ;
List<BookInfo> bookInfos = dao.queryAll();
PageInfo<BookInfo> pageInfo = new PageInfo<>(bookInfos);
dao.queryAll();的结果作为参数传给PageInfo对象
System.out.println(pageInfo.getList().get(0));
}
4.ssm整合
4.1依赖包
-
mybatis.jar -
spring mvc.jar -
mysql.jar -
mybatis-spring.jar -
junit-4.12.jar -
c3p0.jar (数据源) -
servlet-api.jar , jstl.jar, standard.jar -
spring-tx.jar , spring-jdbc.jar -
其他
4.2配置
-
web.xml -
Spring-mvc.xml -
mybatis-config.xml <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
-
mydb.properties -
ssm整合的配置 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:property-placeholder location="classpath:mydb.properties">
</context:property-placeholder>
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="ds"></property>
<property name="configLocation" value="classpath:mybatisconfig.xml"></property>
<property name="mapperLocations" value="classpath:mapper/*.xml">
</property>
</bean>
<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="password" value="${mydb.pwd}"></property>
<property name="user" value="${mydb.user}"></property>
<property name="jdbcUrl" value="${mydb.url}"></property>
<property name="driverClass" value="${mydb.driver}"></property>
</bean>
<bean id="mapperScanner"
class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xsh.ssm.dao"></property>
<property name="sqlSessionFactoryBeanName"
value="sqlSessionFactory"></property>
</bean>
</beans>
4.3ssm+ajax
json转换的jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.11</version>
</dependency>
spring.xml配置转换器
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=utf-8</value>
<value>application/json;charset=utf-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
controller中的使用
@RestController
体类, Object)
@RequestMapping("/emp")
@CrossOrigin(value = "http://127.0.0.1:8848/")
public class EmpController {
@Autowired
EmpService service ;
@RequestMapping("/list")
public Map<String , Object> queryOnePage(@RequestParam(defaultValue =
"1") Integer page ,
@RequestParam(defaultValue = "3") Integer
limit){
PageInfo<Emp> pageInfo = service.queryByPage(page, limit);
Map<String , Object> map = new HashMap<>();
4. 页面上的使用
使用jquery的ajax函数,发送异步请求:
5. 安装postman ,可以测试请求
map.put("count" , pageInfo.getTotal());
数
map.put("code" , 0) ;
map.put("msg" ,"");
map.put("data" ,pageInfo.getList() );
数据
return map;
}
@RequestMapping("/add")
public Map<String ,Object> addEmp(Emp emp){
Boolean aBoolean = service.addEmp(emp);
Map<String , Object> map = new HashMap<>();
map.put("success" , aBoolean);
return map;
}
@RequestMapping("/one")
public Emp queryByEno(Integer eno){
return service.queryByEno(eno);
}
}
jquery使用ajax
$.ajax({
url:"http://localhost:8080/ssm_ajax/emp/add", // 请求地址
data: data.field, // 提交请求的表单的数据
type:"post", // 请求方式
dataType:"json", // 期待的返回值类型
success:function(res){ // res就是响应结果
if(res.success){
layer.msg("添加成功"); // layer.msg-- 弹出一个信息
}else{
layer.msg("添加失败")
}
}
})
5.springboot+mybatis plus
5.1导入mybatis plus的jar包
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
5.2使用mybatis plus自动生成
5.2.1导入需要的bao
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
5.2.2配置运行自动生成的main函数
public class GenMyBatisPlus {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/empdb?
serverTimezone=Asia/Shanghai",
"root", "123456")
.globalConfig(builder -> {
builder.author("fengjm")
.enableSwagger()
.fileOverride()
.outputDir("D:/javaweb/sbmp/src/main/java");
出目录
})
3.3测试功能
4. mybatis plus的分页查询
分页的拦截器的配置
测试分页的功能
.packageConfig(builder -> {
builder.parent("com.xsh.sbmp")
.pathInfo(Collections.singletonMap(OutputFile.xml,
"D://"));
})
.strategyConfig(builder -> {
builder.addInclude("emp" ,"user" , "dept")
.addTablePrefix("t_", "c_");
})
.templateEngine(new FreemarkerTemplateEngine())
引擎模板,默认的是Velocity引擎模板
.execute();
}
}
5.2.3使用
@SpringBootTest
class SbmpApplicationTests {
@Autowired
IEmpService service ;
@Test
public void testSelect(){
Emp byId = service.getById(3);
System.out.println(byId.getEname());
}
}
5.3分页查询
配置分页拦截器的类
@Configuration
public class PageConfig {
@Bean
public MybatisPlusInterceptor pageAdd(){
MybatisPlusInterceptor interceptor =
new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(
new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor ;
}
}
使用分页
@Test
public void testSelect(){
Page<Emp> page =
service.page(new Page<>(1, 5));
List<Emp> records = page.getRecords();
System.out.println(records);
}
5.4条件查询
个条件用and 连接。
emp
@Test
public void query(){
Emp emp = new Emp();
emp.setEjob("yyyy");
emp.setEmanager(1);
QueryWrapper<Emp> empQueryWrapper = new QueryWrapper<>(emp);
List<Emp> list = service.list(empQueryWrapper);
System.out.println(list);
}
DESC
@Test
public void query1(){
QueryWrapper<Emp> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("esalary" , 3000.0);
数据,
queryWrapper.or().lt("eno" , 10);
queryWrapper.like("ename" , "%y%");
queryWrapper.apply(" deptno=1");
queryWrapper.orderByDesc("esalary");
List<Emp> list = service.list(queryWrapper);
}
@Test
public void query2(){
QueryWrapper<Emp> queryWrapper = new QueryWrapper<>();
queryWrapper.select("ename " , "ejob").gt("esalary" , 3000.0);
List<Map<String, Object>> maps = service.listMaps(queryWrapper);
System.out.println(maps);
}
5.5swagger3的使用
jar包
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
添加注解
-
controller @RestController
@RequestMapping("/emp")
@Api(tags = "员工管理模块")
public class EmpController {
@Autowired
IEmpService iEmpService ;
@RequestMapping(value = "/page" , method = RequestMethod.POST)
@ApiOperation(value = "分页查询" , notes = "当前页码的员工们")
public List<Emp> selectPage(@ApiParam(value = "页码" , required = true)
@RequestParam(defaultValue = "1") int
page,
@ApiParam(value = "每页显示的行数" )
@RequestParam(defaultValue = "3") int
limit){
Page<Emp> page1 = iEmpService.page(new Page<>(page, limit));
return page1.getRecords();
}
}
-
实体类 @ApiModel(value = "Emp对象", description = "")
public class Emp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("员工编号")
@TableId(value = "eno", type = IdType.AUTO)
private Integer eno;
@ApiModelProperty("员工名字")
private String ename;
@ApiModelProperty("工作岗位")
private String ejob;
@ApiModelProperty("部门经理")
private Integer emanager;
@ApiModelProperty("入职日期")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" , timezone = "GMT+8")
private LocalDateTime ehiredate;
@ApiModelProperty("工资")
private BigDecimal esalary;
@ApiModelProperty("部门编号")
private Integer deptno;
@ApiModelProperty("员工照片的地址")
private String empImg;
}
启动springboot项目,访问http://localhost:8080/swagger-ui/
单独配置swagger3的类
@Configuration
@EnableOpenApi
public class Swagger3Config {
Boolean swaggerEnabled=true;
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.enable(swaggerEnabled)
.select()
.apis(RequestHandlerSelectors.basePackage("com.hqyj.sbmp.controller"))
.paths(PathSelectors.any())
.build();
}
6. mybatis plus的条件查询
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("员工管理系统")
.description("员工管理系统接口说明文档")
.contact(new Contact("alice","https://xxxx.icu/",
"alice@qq.com"))
.version("1.0")
.build();
}
}
6.springboot+jpa
6.1概念
JPA(java persistence api),是java提供的访问数据库的规范,Hibernate是完全实现了jpa,spring对hibernate实现的jpa进行了封装,提供了spring data jpa,使用spring data jpa的包,实现数据库访问。
sql和hql:
sql:查询的数据库,select * from emp
hql:查询的对象,from emp
6.2使用步骤
-
spring boot 项目的创建 -
spring data jpa包的导入
在pom.xml中导入依赖(idea会自动导入)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
在application.xml中配置连接数据库的信息
#连接数据库的信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shopdb?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
#配置数据库
spring.jpa.database=mysql
#配置数据库方言
#spring.jpa.properties.
#显示sql
spring.jpa.show-sql=true
#spring.jpa.open-in-view=false
entity.java
package com.xsh.sbjpa.entity;
import lombok.Data;
import lombok.ToString;
import javax.persistence.*;
@Data
@ToString
@Entity
@Table(name = "goods_info")
public class GoodsInfo {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name="gi_id")
private Integer giId;
@Column(name="gt_id")
private Integer gtId;
@Column(name="gi_name")
private String giName;
@Column(name="gi_price")
private Double giPrice;
@Column(name="gi_num")
private Integer giNum;
@Column(name="gi_note")
private String giNote;
@Column(name="gi_img")
private Integer giImg;
}
idea中连接数据库来消除报红
然后鼠标停留在报红上,选择左下角,添加对应的表自动修复
Dao.java,继承JpaRepository<>,要添加泛型
package com.xsh.sbjpa.dao;
import com.xsh.sbjpa.entity.GoodsInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface GoodsInfoDao extends JpaRepository<GoodsInfo,Integer> {
}
定义接口IService.java
package com.xsh.sbjpa.service;
import com.xsh.sbjpa.entity.GoodsInfo;
import java.util.List;
public interface IGoodsInfoService {
GoodsInfo getOne(Integer giId);
List<GoodsInfo> getAll();
boolean addGoodsInfo(GoodsInfo goodsInfo);
boolean updateGoodsInfo(GoodsInfo goodsInfo);
boolean deleteGoodsInfo(Integer giId);
}
注意:@Service注解是添加在实现类上,而不是接口类上
ServiceImpl实现接口IService.java
package com.xsh.sbjpa.service.impl;
import com.xsh.sbjpa.dao.GoodsInfoDao;
import com.xsh.sbjpa.entity.GoodsInfo;
import com.xsh.sbjpa.service.IGoodsInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class GoodsInfoServiceImpl implements IGoodsInfoService {
@Autowired
GoodsInfoDao dao;
@Override
public GoodsInfo getOne(Integer giId) {
Optional<GoodsInfo> opt = dao.findById(giId);
if(opt.isPresent()){
return opt.get();
}
return null;
}
@Override
public List<GoodsInfo> getAll() {
return dao.findAll();
}
@Override
public boolean addGoodsInfo(GoodsInfo goodsInfo) {
GoodsInfo gi = new GoodsInfo();
gi.setGiName(goodsInfo.getGiName());
boolean exists = dao.exists(Example.of(gi));
if(!exists){
dao.save(goodsInfo);
return true;
}
return false;
}
@Override
public boolean updateGoodsInfo(GoodsInfo goodsInfo) {
dao.save(goodsInfo);
return true;
}
@Override
public boolean deleteGoodsInfo(Integer giId) {
dao.deleteById(giId);
return true;
}
}
package com.xsh.sbjpa;
import com.xsh.sbjpa.entity.GoodsInfo;
import com.xsh.sbjpa.service.IGoodsInfoService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class SbjpaApplicationTests {
@Autowired
IGoodsInfoService service;
@Test
void testSelect() {
GoodsInfo one = service.getOne(1002);
System.out.println(one);
List<GoodsInfo> all = service.getAll();
System.out.println(all);
}
@Test
void testInsert(){
GoodsInfo goodsInfo = new GoodsInfo();
goodsInfo.setGiName("大西瓜");
goodsInfo.setGiId(1020);
boolean b=service.addGoodsInfo(goodsInfo);
System.out.println("插入"+b);
goodsInfo.setGiName("大西瓜333");
boolean b1=service.addGoodsInfo(goodsInfo);
System.out.println("插入"+b1);
}
@Test
void testUpdate() {
GoodsInfo goodsInfo = new GoodsInfo();
goodsInfo.setGiName("大西瓜");
goodsInfo.setGiId(1020);
goodsInfo.setGiNum(233);
boolean b=service.updateGoodsInfo(goodsInfo);
System.out.println("更新"+b);
}
@Test
void testDelete() {
boolean b=service.deleteGoodsInfo(1020);
System.out.println("删除"+b);
}
}
6.3设置事务
事务(Transaction)是一个不可分割的执行单位,事务中包括的操作要么都做,要么都不做。
使用@Transactional注解可以将方法中执行的sql语句都设置为同一事务
@Transactional使用在方法前,表示为该方法设置事务
@Transactional使用在类前,表示为该类的所有方法设置事务
例:
boolean testTransactional1();
boolean testTransactional2();
testTransactional1没有添加注解,testTransactional2添加了注解
@Override
public boolean testTransactional1() {
GoodsInfo one = new GoodsInfo();
one.setGiId(1021);
one.setGiName("执行1");
dao.save(one);
GoodsInfo two = new GoodsInfo();
one.setGiId(1021);
dao.save(two);
return true;
}
@Override
@Transactional
public boolean testTransactional2() {
GoodsInfo one = new GoodsInfo();
one.setGiId(1021);
one.setGiName("执行1");
dao.save(one);
GoodsInfo two = new GoodsInfo();
one.setGiId(1021);
dao.save(two);
return true;
}
数据库中的结果:
testTransactional1()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bRxNPV7h-1665835053089)(img/image-20221010115323831.png)]
testTransactional2()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0b824nKX-1665835053090)(img/image-20221010115442125.png)]
补充:事务的概念回顾
事务是恢复和并发控制的基本单位;
在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或者整个程序
特性:
事务具有四个特性(ACID):
? 原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)。
- 原子性(atomicity),一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做
- 一致性(consistency),事务必须是使数据库从一个一致性状态变到另一个一致性状态,一致性与原子性是密切相关的
- 隔离性(isolation),一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
- 持久性(durability),持久性也成为永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响
6.4复杂查询
@Autowired
GoodsInfoDao dao;
分页、排序、分页并排序(直接测试dao)
package com.xsh.sbjpa;
import com.xsh.sbjpa.dao.GoodsInfoDao;
import com.xsh.sbjpa.entity.GoodsInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import java.util.List;
@SpringBootTest
public class TestGoodsInfoDao {
@Autowired
GoodsInfoDao dao;
@Test
public void test1(){
int page = 1;
int size=3;
PageRequest pageRequest = PageRequest.of(page, size);
Page<GoodsInfo> all = dao.findAll(pageRequest);
System.out.println(all.getContent());
}
@Test
public void test2(){
List<GoodsInfo> all = dao.findAll(Sort.by(Sort.Direction.ASC, "giNum", "giPrice"));
dao.findAll(Sort.by(Sort.Order.asc("giNum"),Sort.Order.desc("giPrice")));
}
@Test
public void test3(){
PageRequest pageRequest = PageRequest.of(0, 5, Sort.by(Sort.Order.desc("giNum"), Sort.Order.desc("giPrice")));
dao.findAll(pageRequest);
}
}
使用Example查询
使用等于条件
@Test
public void test4(){
GoodsInfo goodsInfo = new GoodsInfo();
goodsInfo.setGiName("大西瓜");
List<GoodsInfo> all = dao.findAll(Example.of(goodsInfo));
System.out.println(all);
}
使用方法命名规则
如果需要使用等于以外的查询条件,需要在Dao.java中自定义方法,方法按照下表命名即可自动添加对应的查询条件
例:
package com.xsh.sbjpa.dao;
import com.xsh.sbjpa.entity.GoodsInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface GoodsInfoDao extends JpaRepository<GoodsInfo,Integer> {
List<GoodsInfo> findByGiPriceGreaterThan(Double giPrice);
List<GoodsInfo> findByGiPriceGreaterThanOrGiNumLessThanEqual(Double giPrice,Integer giNum);
}
@Test
public void test5(){
List<GoodsInfo> all = dao.findByGiPriceGreaterThan(10.0);
List<GoodsInfo> all1 = dao.findByGiPriceGreaterThanOrGiNumLessThanEqual(10.0,20);
}
自定义方法查询
Dao.java
@Query("from GoodsInfo where giName like :giName and giPrice > :giPrice")
List<GoodsInfo> selectByWhere(String giName,Double giPrice);
测试
@Test
public void test6(){
dao.selectByWhere("%西%",10.0);
}
Dao.java
@Query(value = "select gt_name as 'name',sum(gi_num) as num from goods_info,goods_type where goods_info.gt_id=goods_type.gt_id group by goods_type.gt_id",nativeQuery = true)
List<Map<String,Object>> selectByGroupGtId();
测试
@Test
public void test7(){
List<Map<String, Object>> list = dao.selectByGroupGtId();
for (Map<String, Object> map : list) {
Object name = map.get("name");
Object num = map.get("num");
System.out.println(name+" "+num);
}
}
结果(注意Map的使用)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u0BfXS5g-1665835053091)(img/image-20221010163940977.png)]
6.5多表查询
注意:不要使用Lombok中的@ToString方法,会造成StackOverflowError,自己添加toString方法,不要转化字段对应外的属性
6.5.1一对多
一:JavaClass.java (table:java_class)
多:Student.java (table:student)
单向一对多
一:
package com.xsh.sbstujpa.entity;
import lombok.Data;
import javax.persistence.*;
import java.util.List;
@Entity
@Data
@Table(name="java_class")
public class JavaClass {
@Id
@Column(name = "c_id")
private Integer cId;
@Column(name = "c_name")
private String cName;
@Column(name = "c_intro")
private String cIntro;
@OneToMany(fetch=FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name="c_id")
private List<Student> stus;
}
多:
package com.xsh.sbstujpa.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Data
@Table(name="student")
public class Student {
@Id
@Column(name = "stu_id")
private Integer stuId;
@Column(name = "stu_name")
private String stuName;
@Column(name = "stu_sex")
private String stuSex;
@Column(name = "c_id")
private Integer cId;
}
单向多对一
一:
package com.xsh.sbstujpa.entity;
import lombok.Data;
import javax.persistence.*;
import java.util.List;
@Entity
@Data
@Table(name="java_class")
public class JavaClass {
@Id
@Column(name = "c_id")
private Integer cId;
@Column(name = "c_name")
private String cName;
@Column(name = "c_intro")
private String cIntro;
}
多:
package com.xsh.sbstujpa.entity;
import lombok.Data;
import javax.persistence.*;
@Entity
@Data
@Table(name="student")
public class Student {
@Id
@Column(name = "stu_id")
private Integer stuId;
@Column(name = "stu_name")
private String stuName;
@Column(name = "stu_sex")
private String stuSex;
@Column(name = "c_id",insertable = false,updatable = false)
private Integer cId;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="c_id")
private JavaClass javaClass;
}
双向一对多&多对一
一:
package com.xsh.sbstujpa.entity;
import lombok.Data;
import javax.persistence.*;
import java.util.List;
@Entity
@Data
@Table(name="java_class")
public class JavaClass {
@Id
@Column(name = "c_id")
private Integer cId;
@Column(name = "c_name")
private String cName;
@Column(name = "c_intro")
private String cIntro;
@OneToMany(fetch=FetchType.EAGER, cascade = CascadeType.ALL,
mappedBy = "javaClass")
private List<Student> stus;
}
多:
package com.xsh.sbstujpa.entity;
import lombok.Data;
import javax.persistence.*;
@Entity
@Data
@Table(name="student")
public class Student {
@Id
@Column(name = "stu_id")
private Integer stuId;
@Column(name = "stu_name")
private String stuName;
@Column(name = "stu_sex")
private String stuSex;
@Column(name = "c_id",insertable = false,updatable = false)
private Integer cId;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="c_id")
private JavaClass javaClass;
}
6.5.2多对多
course表对应student表,数据库中需要多对多联系的中间表
单向多对多
package com.xsh.sbstujpa.entity;
import lombok.Data;
import javax.persistence.*;
import java.util.List;
@Entity
@Data
@Table(name = "course")
public class Course {
@Id
@Column(name = "c_id")
private String cId;
@Column(name = "c_name")
private String cName;
@Column(name = "t_id")
private Integer tId;
@ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
@JoinTable(name="cou_stu",
joinColumns = {@JoinColumn(name="c_id")},
inverseJoinColumns = {@JoinColumn(name = "stu_id")}
)
private List<Student> stus;
}
双向多对多
在一对多的基础上另一个表:
package com.xsh.sbstujpa.entity;
import lombok.Data;
import lombok.ToString;
import javax.persistence.*;
import java.util.List;
@Entity
@Data
@Table(name="student")
public class Student {
@Id
@Column(name = "stu_id")
private Integer stuId;
@Column(name = "stu_name")
private String stuName;
@Column(name = "stu_sex")
private String stuSex;
@Column(name = "c_id",insertable = false,updatable = false)
private Integer cId;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="c_id")
private JavaClass javaClass;
@ManyToMany(fetch = FetchType.EAGER,
mappedBy = "stus")
private List<Course> courses;
@Override
public String toString() {
return "Student{" +
"stuId=" + stuId +
", stuName='" + stuName + '\'' +
", stuSex='" + stuSex + '\'' +
", cId=" + cId +
'}';
}
}
#### 6.5.3一对一
只需要在一方使用添加对应属性和@OneToOne注解和@JoinColumn注解
thymeleaf官网https://www.thymeleaf.org/
如果需要在springboot中使用thymeleaf和SSM中使用jsp的方式类似
将html文件放到resources/templates下
在html中设置一个thymeleaf官网的命名空间,一般用th作为标识符
```html
<!-- 设置官网的命名空间-->
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
在需要显示动态数据的标签上添加th:属性=${响应的变量名},text标识标签中的文本内容
<h2 th:text="${word}">欢迎xx!</h2>
<img th:src="@{/img/c5.jpg}">
或者使用thymeleaf的其他选项,如循环、判断等
<table>
<tr>
<td>班级名</td>
<td>班级简介</td>
</tr>
<tr th:each="jl:${javaclass}">
<td th:text="${jl.cName}">名字</td>
<td th:text="${jl.cIntro}">介绍</td>
</tr>
</table>
例:
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/css/main.css">
<script src="/js/jquery.js"></script>
<title>Title</title>
</head>
<body>
<h2 th:text="${word}">欢迎xx!</h2>
<table>
<tr>
<td>班级名</td>
<td>班级简介</td>
</tr>
<tr th:each="jl:${javaclass}">
<td th:text="${jl.cName}">名字</td>
<td th:text="${jl.cIntro}">介绍</td>
</tr>
</table>
<img th:src="@{/img/c5.jpg}">
<script>
$("tr").css("color","white")
</script>
</body>
</html>
在controller的请求中和使用jsp时一样,添加ModelMap参数来响应数据,方法返回html去掉后缀的文件名
@Controller
public class TClassController {
Logger logger = LoggerFactory.getLogger(TClassController.class);
@Autowired
JavaClassDao dao;
@RequestMapping("list")
public String query(ModelMap map){
map.put("word","tom,下午好");
List<JavaClass> all = dao.findAll();
map.put("javaclass",all);
return "first";
}
}
private Integer stuId; @Column(name = “stu_name”) private String stuName; @Column(name = “stu_sex”) private String stuSex; @Column(name = “c_id”,insertable = false,updatable = false) private Integer cId;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="c_id")
private JavaClass javaClass;
//委托另外一方维护设置
@ManyToMany(fetch = FetchType.EAGER,
mappedBy = "stus")
private List<Course> courses;
@Override
public String toString() {
return "Student{" +
"stuId=" + stuId +
", stuName='" + stuName + '\'' +
", stuSex='" + stuSex + '\'' +
", cId=" + cId +
'}';
}
}
6.5.3一对一
只需要在一方使用添加对应属性和@OneToOne注解和@JoinColumn注解
thymeleaf官网https://www.thymeleaf.org/
如果需要在springboot中使用thymeleaf和SSM中使用jsp的方式类似
将html文件放到resources/templates下
在html中设置一个thymeleaf官网的命名空间,一般用th作为标识符
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
在需要显示动态数据的标签上添加th:属性=${响应的变量名},text标识标签中的文本内容
```html
<h2 th:text="${word}">欢迎xx!</h2>
<img th:src="@{/img/c5.jpg}">
或者使用thymeleaf的其他选项,如循环、判断等
<table>
<tr>
<td>班级名</td>
<td>班级简介</td>
</tr>
<tr th:each="jl:${javaclass}">
<td th:text="${jl.cName}">名字</td>
<td th:text="${jl.cIntro}">介绍</td>
</tr>
</table>
例:
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/css/main.css">
<script src="/js/jquery.js"></script>
<title>Title</title>
</head>
<body>
<h2 th:text="${word}">欢迎xx!</h2>
<table>
<tr>
<td>班级名</td>
<td>班级简介</td>
</tr>
<tr th:each="jl:${javaclass}">
<td th:text="${jl.cName}">名字</td>
<td th:text="${jl.cIntro}">介绍</td>
</tr>
</table>
<img th:src="@{/img/c5.jpg}">
<script>
$("tr").css("color","white")
</script>
</body>
</html>
在controller的请求中和使用jsp时一样,添加ModelMap参数来响应数据,方法返回html去掉后缀的文件名
@Controller
public class TClassController {
Logger logger = LoggerFactory.getLogger(TClassController.class);
@Autowired
JavaClassDao dao;
@RequestMapping("list")
public String query(ModelMap map){
map.put("word","tom,下午好");
List<JavaClass> all = dao.findAll();
map.put("javaclass",all);
return "first";
}
}
end
|