前言
前面我們了解了Spring MVC的基本使用,其實和.NET或.NET Core MVC無異,只是語法不同而已罷了,本節我們將和和數據庫打交道,從最基礎的JDBC講解起,文中若有錯誤之處,還望指正。
JDBC Demo
我們需要下載三個包:JDBC驅動包(mysql-connector-java)、spring boot啟用jdbc(spring-boot-starter-jdbc)、對數據進行序列化的json包(jackson-databind),如下:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
接下來我們在配置文件中,通過JDBC連接MySQL數據庫,如下:
spring.datasource.url = jdbc:mysql://localhost:3306/user?serverTimezone=UTC spring.datasource.username = root spring.datasource.password = root
這里需要注意的是:對於不同的JDBC驅動版本,可能會拋出如下錯誤,這是由於在JDBC指定版本中存在的bug,所以要么如上顯式指定serverTimezone,要么添加JDBC版本
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
接下來我們定義對用戶進行增、刪、改、查的接口,如下:
public interface UserRepository { int save(User user); int update(User user); int deleteById(int id); List<User> findAll(); }
接下來我們再來看用戶類,我們將對提交用戶信息通過注解進行校驗,同時我們對之前添加的愛好的數據類型為數組序列化為JSON后存到MySQL數據庫,如下:
public class User { private ObjectMapper objectMapper = new ObjectMapper(); public User() { } public User(int userId, String firstName, String lastName, String gender, String email, String userName, String password, String country, String favoritesJson) throws JsonProcessingException { this.userId = userId; this.firstName = firstName; this.lastName = lastName; this.gender = gender; this.email = email; this.userName = userName; this.password = password; this.country = country; this.favorites = objectMapper.readValue(favoritesJson, new TypeReference<String[]>() { }); } private int userId; @NotNull(message = "名字必填") private String firstName; @NotNull(message = "姓氏必填") private String lastName; @NotNull(message = "性別必填") private String gender; @NotNull(message = "郵箱必填") @Email(message = "請輸入有效的郵箱") private String email; @NotNull(message = "用戶名必填") private String userName; @NotNull(message = "密碼必填") private String password; private String country; public int getUserId() { return userId; } public String getFavoritesJson() { String favoritesJson = null; try { favoritesJson = objectMapper.writeValueAsString(this.favorites); } catch (JsonProcessingException ex) { } return favoritesJson; } public void setUserId(int userId) { this.userId = userId; } private String[] favorites; public String[] getFavorites() { return favorites; } public void setFavorites(String[] favorites) { this.favorites = favorites; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
最后則是實現上述用戶接口,這里我們使用JDBC中的參數化類(避免SQL注入)進行增刪改查,如下:
@Repository public class NamedParameterJdbcUserRepository implements UserRepository { @Autowired public NamedParameterJdbcTemplate namedParameterJdbcTemplate; @Override public int save(User user) { MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource(); mapSqlParameterSource.addValue("userName",user.getUserName()); mapSqlParameterSource.addValue("password",user.getPassword()); mapSqlParameterSource.addValue("firstName",user.getFirstName()); mapSqlParameterSource.addValue("lastName",user.getLastName()); mapSqlParameterSource.addValue("gender",user.getGender()); mapSqlParameterSource.addValue("email",user.getEmail()); mapSqlParameterSource.addValue("country",user.getCountry()); mapSqlParameterSource.addValue("favorites",user.getFavoritesJson()); return namedParameterJdbcTemplate.update( "insert into users (userName, password,firstName,lastName,gender,email,country,favorites)" + " values(:userName,:password,:firstName,:lastName,:gender,:email,:country,:favorites)", mapSqlParameterSource); } @Override public int update(User user) { return 0; } @Override public int deleteById(int id) { MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource(); mapSqlParameterSource.addValue("userId", id); return namedParameterJdbcTemplate.update("delete from users where userId = :userId", mapSqlParameterSource); } @Override public List<User> findAll() { return namedParameterJdbcTemplate.query( "select * from users", (rs, rowNum) -> { try { return new User( rs.getInt("userId"), rs.getString("firstName"), rs.getString("lastName"), rs.getString("gender"), rs.getString("email"), rs.getString("userName"), rs.getString("password"), rs.getString("country"), rs.getString("favorites") ); } catch (JsonProcessingException e) { e.printStackTrace(); return null; } }); } }
然后在進行提交用戶時,在上一節內容基礎上進行改造,添加校驗注解,若有錯誤則返回,否則提交成功后則跳轉到用戶列表,如下:
@RequestMapping(value = "/user", method = RequestMethod.POST) public String user(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "user"; } else { jdbcUserRepository.save(user); return "users"; } }
這里需要注意的是:對於空字符串即使添加了校驗注解后依然會忽略,所以我們還需要初始化綁定器注解去除空字符串並對其進行校驗,如下:
@InitBinder public void initBinder(WebDataBinder dataBinder) { StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true); dataBinder.registerCustomEditor(String.class, stringTrimmerEditor); }
表單提交我們使用的是spring提供給我們的庫,渲染用戶列表,我們則是通過腳本並利用bootstrap-table實現,最終界面所呈現出的效果,如下:
總結
如上只是給出了部分重要代碼,這里我已經將本節通過JDBC進行增刪改查代碼上傳到github(https://github.com/wangpengxpy/SpringBoot),切換分支即可,后續會將每一塊內容分別創建一個分支,以便供我復習和有需要的童鞋使用,本節我們到此結束,我們下節見。