※PK是流水號的問題
首先先創一張表CREATE TABLE CHESS( CHESS_NO NUMBER(10), NAME VARCHAR(10), PRICE NUMBER(5), PRODUCT_DATE DATE, CONSTRAINT CHESS_PK PRIMARY KEY(CHESS_NO) ); CREATE SEQUENCE CHESS_SEQUENCE INCREMENT BY 1 START WITH 1 NOMAXVALUE NOCYCLE CACHE 10; COMMENT ON TABLE CHESS IS '棋表'; COMMENT ON COLUMN CHESS.CHESS_NO IS '棋編號'; COMMENT ON COLUMN CHESS.NAME IS '棋名稱'; COMMENT ON COLUMN CHESS.PRICE IS '棋價錢'; COMMENT ON COLUMN CHESS.PRODUCT_DATE IS '棋的生產日期';
然後增加棋類,欄位對應好,然後給setter/getter,下面是Chess.xml
<insert id="insert" parameterType="Chess"> INSERT INTO CHESS( <include refid="column" /> ) VALUES(CHESS_SEQUENCE.NEXTVAL, #{name}, #{price}, #{productDate}) </insert>
增加別名時,因為是同一個包,乾脆就增加package就可以了,mybatis會去這個包找,還要記得Chess.xml要設定
<typeAliases> <!-- <typeAlias type="org.mybatis.model.Dept" alias="Dept" /> --> <!-- <typeAlias type="org.mybatis.model.Chess" alias="Chess" /> --> <package name="org.mybatis.model"/> </typeAliases> <!--資料庫操作省略--> <mappers> <mapper resource="org/mybatis/model/Dept.xml" /> <mapper resource="org/mybatis/model/Chess.xml" /> </mappers>
※新增時,PK的問題
這時會發現新增時,PK居然是nullSystem.out.println("----------Chess.insert----------"); Chess chess = new Chess(); chess.setName("五子棋"); chess.setPrice(35); chess.setProductDate(new Date()); int suc = sqlSession.insert("Chess.insert", chess); System.out.println("成功新增" + suc + "筆!"); System.out.println("PK=" + chess.getChessNo()); System.out.println("name=" + chess.getName()); System.out.println("price=" + chess.getPrice()); System.out.println("productDate=" + chess.getProductDate());
由於我用的是oracle,所以oracle的解法是這樣
<insert id="insert" parameterType="Chess"> <!-- selectKey因為設定BEFORE,所以會在執行之前,會先執行裡面的語法到setChessNo裡 --> <selectKey keyProperty="chessNo" order="BEFORE" resultType="java.lang.Integer"> SELECT CHESS_SEQUENCE.NEXTVAL FROM DUAL </selectKey> INSERT INTO CHESS( <include refid="column" /> )
以下兩行選擇其一,一般會用第二種 <!--VALUES(CHESS_SEQUENCE.CURRVAL, #{name}, #{price}, #{productDate})-->
VALUES(#{chessNo}, #{name}, #{price}, #{productDate}, #{clazz}, #{score}, #{school}) </insert>
※查詢時,欄位名稱的問題
新增一組PK查詢<select id="getChessById" parameterType="java.lang.Integer" resultType="Chess" > SELECT <include refid="column" /> FROM CHESS WHERE CHESS_NO = #{chessNo} </select>
測試類如下,其實還要增加查不到是null的問題,才不會報Exception,測試就算了
System.out.println("----------Chess.getChessById----------"); Chess chess = sqlSession.selectOne("Chess.getChessById", 12); System.out.println("chessNo=" + chess.getChessNo()); System.out.println("name=" + chess.getName()); System.out.println("price=" + chess.getPrice()); System.out.println("productDate=" + chess.getProductDate());此時發現chessNo和productDate是null,因為資料庫有_,java沒有,他把他放到java那裡了,所以可以增加個別名,我最後面剛好是PRODUCT_DATE,所以直接加在後面
<select id="getChessById" parameterType="java.lang.Integer" resultType="Chess"> SELECT <include refid="column" /> as productDate FROM CHESS WHERE CHESS_NO = #{chessNo} </select>但chessNo還是null,因為我沒加別名,但仔細想想,這個做法真是太爛了,一點都不好維護,所以mybatis提供了一個叫resultMap的東西,resultMap和resultType只能選擇其一,做法如下:
<resultMap type="Chess" id="ChessInterface"> <result property="chessNo" column="CHESS_NO" /> <result property="productDate" column="PRODUCT_DATE" /> </resultMap> <select id="getChessById" parameterType="java.lang.Integer" resultMap="ChessInterface" > SELECT <include refid="column" /> FROM CHESS WHERE CHESS_NO = #{chessNo} </select>type有別名的關係,可以直接寫,id隨便取
然後將我們剛剛的resultType改成resultMap,裡面放resultMap的id即可
我目前做的專案都是把全部的屬性打在裡面,像這樣:
<resultMap type="Chess" id="ChessInterface"> <id property="chessNo" column="CHESS_NO" /> <result property="name" column="NAME" /> <result property="price" column="PRICE" /> <result property="productDate" column="PRODUCT_DATE" /> </resultMap>我把PK改成id標籤,結果是一樣的,不過既然是PK,最好就用id,我還試不出差在哪 剛剛第一種做法直接加在欄位後面是不分大小寫的,但property是有分的喔!
還可以用建構子設值,首先在 java bean 的類別裡用工具產生一個所有欄位的建構子,然後xml如下設定(注意順序問題):
<constructor> <idArg column="CHESS_NO" javaType="java.lang.Integer" /> <arg column="NAME" javaType="java.lang.String" /> <arg column="PRICE" javaType="java.lang.Integer" /> <arg column="PRODUCT_DATE" javaType="java.util.Date" /> </constructor>
※jdbcType
預設是 OTHER,這在 Oracle 會不知道如何處理,可以改為 NULL 即可譬如在新增時,欄位是可以 null 的,但 insert 時,還是會報 OTHER 不知道怎麼處理的錯誤,所以可以使用 #{fieldName, jdbcType=NULL}
但如果有很多這樣的東西,可以設定在全域設定這個值,就是在設定資料庫帳密的地方,寫在 properties 同級的下面,如下:
<settings> <setting name="jdbcTypeForNull" value="NULL" /> </settings>
※大小寫要注意
※@Results、@Result、@ResultMap
@Mapper public interface DeptMapper2 { @Results(id = "d2", value = { @Result(id = true, column = "deptno", property = "dno"), // @Result(column = "dname", property = "name"), @Result(column = "loc", property = "loc") }) @Select("select * from dept where deptno = #{deptNo}") public Dept2 getDeptById(int id); @ResultMap("d2") @Select("select * from dept") public List<Dept2> getAllDept2(); }
※使用 @Results 時,不能像 XML一樣單獨定義,其他的方法可以用 @ResultMap 使用,但本身有 @Results 不能再用 @ResultMap
※@Results 寫的地方有差,以此例來說,寫在getAllDept2 上面,那 getDeptById 就算用 @ResultMap 也抓不到
※@SelectProvider
@ResultMap("d2") @SelectProvider(type = MyProvider.class, method="noParam") public List<Dept2> providerTest(); @ResultMap("d2") @SelectProvider(type = MyProvider.class, method="param") public Dept2 providerTest2(@Param("xxx") int id); public class MyProvider { public String noParam() { return "select * from dept"; } public static String param(Map<String, Integer> map) { return "select * from dept where deptno = " + map.get("xxx"); } }
※使用 @SelectProvider 時,可以用 static,但不能使用 overloading
※有參數時,必須用 Map 接,Key 固定給 String,Value 和資料庫的型態對應好即可,如果怕出錯可給 Object
※@InsertProvider、@DeleteProvider、@UpdateProvider 也差不多
沒有留言:
張貼留言