Spring Boot实战——数据交互页(涉及数据库)

 

  之前写过一篇博客是不涉及数据库的数据交互页,其实该博客的实战性不强,因为数据最终都是需要存储在数据库中的,所以这次我觉得补充一篇有关数据库的数据交互页。

 

  首先我使用的数据库是MySQL这类关系型数据库,至于NoSQL这类,例如MongoDB这类我暂时不说着。管理数据库语言我是使用spring boot支持的spring data jpa,主要该语言完全脱离数据库语言,同时去xml化也很好,当然,没有十全十美的语言,也会有些瑕疵,后面我会补充Mybatis的使用。

 

一. Spring Data Jpa

提供一篇博客参考:SpringBoot学习笔记九:Spring Data Jpa的使用

  

首先,导入相关依赖:

<!--mysql的导入-->
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
</dependency>

<!--spring data jpa的导入-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!--jdbc的导入-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

  然后进行配置文件:

spring:
  datasource:
    #用户名
    username: root
    #密码
    password: 123456
    #设置url,其中//后是连接的ip地址,3306是mysql的端口号,xxxx是建的数据库名
    url: jdbc:mysql://localhost:3306/user
    driver-class-name: com.mysql.jdbc.Driver

  #进行其他设置
  jpa:
    hibernate:
      #create根据定义的类自动生成表格(每次重启便会删除前次的表)
      #除了create,常用的是update,第一次也会生成,但之后操作不会删表
      ddl-auto: update
    #在控制台看到sql语句,方便调试
    show-sql: true

注意:如果后面运行的时候有错误:

(1)ava.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

这是由于系统时间错误,这时候在配置时要修改url

url: jdbc:mysql://localhost:3306/user?serverTimezone=GMT%2B8

(2)org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]

这是entityManagerFactory注入bean错误,产生这个错误的原因有很多,我遇到过很多次,这时候我们要检查:

(1)依赖注入有无问题(主要是jdbc的注入)

(2)配置文件(application.properties或application.yml)中的配置有无出错,好好检查

(3)@Entity有无写(导入包应该为import javax.persistence.*;)

(4)@Service有无写,查看是否是使用xxxService而不是xxxServiceImpl

 

 

 

  和不涉及数据库一样,涉及数据库也是有固定的流程的,首先当然是建立实体类,而jpa要求在实体类中做一些准备,也是要求注明实体类为Entiy,指定自增组件等等操作,我们看代码:

@Entity  //自动生成表
@Table(name = "user")  //生成表名,若无设置,则使用类名作为表名
public class User {

    @Id  //指定id类型
    @GeneratedValue(strategy = GenerationType.IDENTITY) //自增主键
    private Integer id;

    @NotBlank   //不能为空
    @Column(nullable = false,length = 50)  //指定不能为空,同时最大长度为50
    private String username;

    @Email  //指定为email格式,出错则报错
    @NotBlank
    @Column(nullable = false,length = 50)
    private String email;


    public User(){
    }

    public User(String username,String email){
         this.username=username;
         this.email=email;
    }
 
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
   
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getUsername() {
        return username;
    }

    public void setEmail(String email) {
        this.email = email;
    }
    
    public String getEmail() {
        return email;
    }  
}

  里面是包括几个标签(标签的作用我已注解,仍不是很明白的话可以上网查一下)的使用,同时含有构造函数和get和set方法。

 

  Spring Data Jpa是要建立一个接口继承JpaRepository的,而该接口内部已经帮助我们实现了大部分数据库操作,我们仅需要调用即可。其中如果还有其他特殊操作,比如根据用户名查找用户,这时候我们仅需要根据一个固定的格式编写函数,则该接口会自动帮忙实现数据库操作语言,代码如下:

//继承该接口,其中接口括号中第一个值应该是实体类,第二个值是实体类中id的类型
//接口中不需要编写数据库相应的操作,也不需要编写函数,接口会自动生成
//特殊操作,即除去查找全体,根据id查找,添增实体,根据id修改,根据id删除外
//例如根据用户名查询用户,则需要按照固定格式,如findByXxx()编写;
public interface UserRepository extends JpaRepository<User,Integer> {
    //根据用户名查询用户
    User findByUsername(String username);
}

 

  实现了接口其实可以直接编写controller层了,但是为了代码公式化,我们必须引入service层,在该层,除了将原本接口内的方法继承调用以外,我们还可以做事务化管理,缓存操作等等。

  第一步理所当然是建立service层的接口:

/* *
* user的service层接口
* */
public interface UserService  {
 
    //查找全部用户
    List<User> findAll();

    //根据用户id查找用户
    User findById(Integer id);

    //保存或修改用户
    User saveOrUpdateUser(User user);

    //根据用户id删除
    void deleteById(Integer id);
    
    //根据用户名查找用户
    User findByUsername(String username);
}

 再实现接口的方法: 

//service接口的实现
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserRepository userRepository;
 
    //查找全部用户
    @Override
    @Transactional
    public List<User> findAll() {
        return userRepository.findAll();
    }

    //通过id查找用户
    @Override
    @Transactional
    public User findById(Integer id) {
        return userRepository.findOne(id);
    }

    //保存或修改用户
    //检查异常
    @Override
    @Transactional
    public User saveOrUpdateUser(User user) {
        try{
           userRepository.save(user);
        }catch (Exception e){
            throw new RuntimeException("Add User Error: "+e.getMessage());
        }
        return user;
    }

    //根据用户id删除用户
    @Override
    @Transactional
    public void deleteById(Integer id) {
         userRepository.delete(id);
    }

    //根据用户名查找用户
    @Override
    @Transactional
    public User findByUsername(String username) {
        return userRepository.findByUsername(username);
    }
}

  其中@Transactional是事务管理的标签。

 

 

  再接下来是controller层,其实controller层的实现和之前不涉及数据库的那篇博客有些类似,其实实现都是一样的,还有后面前端的部分实现也差不多,我就直接拷贝过来修改,将原本Put和Delete请求添加上去:

请求类型

请求路径

功能

GET

/mysql

获取数据库列表

POST

/mysql

创建一个对象

GET

/mysql/{id}

通过id查询一个对象

PUT

/mysql/{id}

通过id修改一个对象

DELETE

/mysql/{id}

通过id删除一个对象

controller层修改为:

@RestController
@RequestMapping("/users")
public class UserController {
 
	@Autowired
	private UserRepository userRepository;
 
	/**
	 * 查询所有用户
	 */
	@GetMapping
	public ModelAndView list(Model model) {
		model.addAttribute("userList", userRepository.listUsers());
		model.addAttribute("title", "用户管理");
		return new ModelAndView("users/list","userModel",model);
	}
 
	/**
	 * 根据 id 查询用户
	 */
	@GetMapping("{id}")
	public ModelAndView view(@PathVariable("id") Long id, Model model) {
		User user = userRepository.getUserById(id);
		model.addAttribute("user", user);
		model.addAttribute("title", "查看用户");
		return new ModelAndView("users/view","userModel",model);
	}
 
	/**
	 * 获取创建表单页面
	 */
	@GetMapping("/form")
	public ModelAndView createForm(Model model) {
		model.addAttribute("user", new User());
		model.addAttribute("title", "创建用户");
		return new ModelAndView("users/form","userModel",model);
	}
 
	/**
	 * 保存用户
	 */
	@PostMapping
	public ModelAndView saveUser(User user) {
		userRepository.saveOrUpdateUser(user);
		return new ModelAndView("redirect:/users");// 重定向到 list页面
	}

     /**
	 * 获取修改用户的界面
	 */
	@GetMapping("/modify/{id}")
	public ModelAndView modify(@PathVariable("id") Long id, Model model) {
		User user = userRepository.getUserById(id);
		model.addAttribute("user", user);
		model.addAttribute("title", "修改用户");
		return new ModelAndView("users/form","userModel",model);
	}
 
     /**
	 * 修改用户
	 */
	@PutMapping
	public ModelAndView UpdateUser(User user) {
		userRepository.saveOrUpdateUser(user);
		return new ModelAndView("redirect:/users");// 重定向到 list页面
	}

	/**
	 * 删除用户
	 */
	@DeleteMapping("/delete/{id}")
	public ModelAndView delete(@PathVariable("id") Long id) {
		userRepository.deleteUser(id);
		return new ModelAndView("redirect:/users"); // 重定向到 list页面
	}
 
}

 

 

  前端thymeleaf由于对put和delete请求不支持,所以需要使用“_method”的方式实现,即:

<!--修改-->
<form  th:action="@{/user/}+${user.id}" method="post">
	<input type="hidden" name="_method" value="put">
	<!--修改按钮-->
	<a type="submit" class="btn btn-primary btn-sm">修改</button>
</form>
<!--删除-->
<form  th:action="@{/user/}+${user.id}" method="post">
	<input type="hidden" name="_method" value="delete">
	<!--删除按钮-->
	<button  type="submit" class="btn btn-danger btn-sm">删除</button>
</form>

所以我们要在原本的前端页面中进行修改,里面还是包含着一个list页面,个人信息界面和form界面:

List页面:

<body>
<h3 th:text="${userModel.title}">waylau</h3>
<div>
	<a href="/users/form.html" th:href="@{/users/form}">创建用户</a>
</div>
<table border="1">
	<thead>
	<tr>
		<td>ID</td>
		<td>Email</td>
		<td>Name</td>
	</tr>
	</thead>
	<tbody>
	<tr th:if="${userModel.userList.size()} eq 0">
		<td colspan="3">没有用户信息!</td>
	</tr>
	<tr th:each="user : ${userModel.userList}">
		<td th:text="${user.id}"></td>
		<td th:text="${user.email}"></td>
		<td ><a th:href="@{'/users/'+${user.id}}" th:text="${user.name}"></a></td>
	</tr>
	</tbody>
</table>
</body>

  个人信息界面:

<body>
<h3 th:text="${userModel.title}">waylau</h3>
<div>
	<P><strong>ID:</strong><span th:text="${userModel.user.id}"></span></P>
	<P><strong>Name:</strong><span th:text="${userModel.user.name}"></span></P>
	<P><strong>Email:</strong><span th:text="${userModel.user.email}"></span></P>
</div>
<div>
   <!--删除-->
   <form  th:action="@{/user/delete}+${user.id}" method="post">
	   <input type="hidden" name="_method" value="delete">
	   <button  type="submit" class="btn btn-danger btn-sm">删除</button>
    </form>
   <!--修改-->
    <a th:href="@{'/users/modify/'+${userModel.user.id}}">修改</a>
</div>
</body>

  form表单:

<body>
<h3 th:text="${userModel.title}">waylau</h3>
<form action="/users" th:action="@{/users}" method="POST" th:object="${userModel.user}">

    <!--put请求-->
    <input type="hidden" name="_method" value="put" th:if="${userModel.user!=null}">
    <input type="hidden" name="id" th:if="${userModel.user!=null}" 
    th:value="${userModel.user.id}" >

	<input type="hidden" name="id" th:value="*{id}">
	名称:<br>
	<input type="text" name="name" th:value="*{name}">
	<br>
	邮箱:<br>
	<input type="text" name="email" th:value="*{email}">
	<input type="submit" value="提交">
</form>
</body>

   通过前端后端结合就可以实现数据交互了

 

 

二. MyBatis

  首先,仍是要导入依赖:

<!--mysql的导入-->
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
</dependency>

<!--jdbc的导入-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<!-- mybatis的导入 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

   配置文件:

spring:
  datasource:
    #用户名
    username: root
    #密码
    password: 123456
    #设置url,其中//后是连接的ip地址,3306是mysql的端口号,xxxx是建的数据库名
    url: jdbc:mysql://localhost:3306/user
    driver-class-name: com.mysql.jdbc.Driver

  MyBatis在Spring时代还需要配置mapping,而现在可以使用注解的方式来代替原本的配置mapping。现如今它仅需要在启动类(也就是项目构建就存在的类)中加入注解,表明mybatis的新型mapper在哪个具体的包下面即可:

  该项目路径中,包Mapper是我存放的mapper类,则我需要在LotterySystem02Applocation启动类中加入注解:

@MapperScan("com.scnu.lotterysystem.Mapper") 

  当然,还可以在每个mapper类上注解@Mapper,效果一样。@MapperScan只是扫描注明的包下的每个类,并将其标识为@Mapper

 

  说完基本,当然是要先建立实体类,仍是user:

//user实体类
public class user {
    private Integer id;
    private String name;
    private String email;

    public user(){

    }
    public user(Integer id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    @Override  //重构toString函数
    public String toString() {
        return "user{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

   

  然后就是建立mapper的接口,这次建立mapper是使用注解的方法,当然仍要使用到数据库操作语言,这是mybatis的特色:

@Mapper
public interface UserMapper {

    @Select("SELECT * FROM user WHERE id = #{id}")
    public user getUserById(Integer id);

    @Update("UPDATE user SET name=#{name},email=#{email} WHERE id=#{id}")
    public void updateUser(user user);

    @Delete("DELETE FROM user WHERE id=#{id}")
    public void deleteById(Integer id);

    @Insert("INSERT INTO user(name,email) VALUES(#{name},#{email})")
    public void insertUser(user user);
}

  这完成以后就类似于建立了一个JPA中的repository,我们可以建立service层来使用即可,其他步骤(建立controller,前端设计)和上面一样

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值