自定义Cassandra数据类型
在博客文章《 從Java連接到Cassandra》中 ,我提到了用Java 實現的Cassandra Java開發人員的一個優勢是能夠創建自定義 Cassandra數據類型 。 在這篇文章中,我將詳細介紹如何執行此操作。
Cassandra具有許多內置的數據類型 ,但是在某些情況下,可能需要添加自定義類型。 通過擴展org.apache.cassandra.db.marshal.AbstractType類,可以在Java中實現Cassandra定制數據類型。 擴展此方法的類必須最終實現具有以下簽名的三個方法:
下一個代碼清單中顯示了本文的AbstractType示例實現。
UnitedStatesState.java –擴展AbstractType
package dustin.examples.cassandra.cqltypes;import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.serializers.MarshalException; import org.apache.cassandra.serializers.TypeSerializer;import java.nio.ByteBuffer;/*** Representation of a state in the United States that* can be persisted to Cassandra database.*/ public class UnitedStatesState extends AbstractType {public static final UnitedStatesState instance = new UnitedStatesState();@Overridepublic ByteBuffer fromString(final String stateName) throws MarshalException{return getStateAbbreviationAsByteBuffer(stateName);}@Overridepublic TypeSerializer getSerializer(){return UnitedStatesStateSerializer.instance;}@Overridepublic int compare(Object o1, Object o2){if (o1 == null && o2 == null){return 0;}else if (o1 == null){return 1;}else if (o2 == null){return -1;}else{return o1.toString().compareTo(o2.toString());}}/*** Provide standard two-letter abbreviation for United States* state whose state name is provided.** @param stateName Name of state whose abbreviation is desired.* @return State's abbreviation as a ByteBuffer; will return "UK"* if provided state name is unexpected value.*/private ByteBuffer getStateAbbreviationAsByteBuffer(final String stateName){final String upperCaseStateName = stateName != null ? stateName.toUpperCase().replace(" ", "_") : "UNKNOWN";String abbreviation;try{abbreviation = upperCaseStateName.length() == 2? State.fromAbbreviation(upperCaseStateName).getStateAbbreviation(): State.valueOf(upperCaseStateName).getStateAbbreviation();}catch (Exception exception){abbreviation = State.UNKNOWN.getStateAbbreviation();}return ByteBuffer.wrap(abbreviation.getBytes());} }上面的類列表引用了State枚舉,如下所示。
State.java
package dustin.examples.cassandra.cqltypes;/*** Representation of state in the United States.*/ public enum State {ALABAMA("Alabama", "AL"),ALASKA("Alaska", "AK"),ARIZONA("Arizona", "AZ"),ARKANSAS("Arkansas", "AR"),CALIFORNIA("California", "CA"),COLORADO("Colorado", "CO"),CONNECTICUT("Connecticut", "CT"),DELAWARE("Delaware", "DE"),DISTRICT_OF_COLUMBIA("District of Columbia", "DC"),FLORIDA("Florida", "FL"),GEORGIA("Georgia", "GA"),HAWAII("Hawaii", "HI"),IDAHO("Idaho", "ID"),ILLINOIS("Illinois", "IL"),INDIANA("Indiana", "IN"),IOWA("Iowa", "IA"),KANSAS("Kansas", "KS"),LOUISIANA("Louisiana", "LA"),MAINE("Maine", "ME"),MARYLAND("Maryland", "MD"),MASSACHUSETTS("Massachusetts", "MA"),MICHIGAN("Michigan", "MI"),MINNESOTA("Minnesota", "MN"),MISSISSIPPI("Mississippi", "MS"),MISSOURI("Missouri", "MO"),MONTANA("Montana", "MT"),NEBRASKA("Nebraska", "NE"),NEVADA("Nevada", "NV"),NEW_HAMPSHIRE("New Hampshire", "NH"),NEW_JERSEY("New Jersey", "NJ"),NEW_MEXICO("New Mexico", "NM"),NORTH_CAROLINA("North Carolina", "NC"),NORTH_DAKOTA("North Dakota", "ND"),NEW_YORK("New York", "NY"),OHIO("Ohio", "OH"),OKLAHOMA("Oklahoma", "OK"),OREGON("Oregon", "OR"),PENNSYLVANIA("Pennsylvania", "PA"),RHODE_ISLAND("Rhode Island", "RI"),SOUTH_CAROLINA("South Carolina", "SC"),SOUTH_DAKOTA("South Dakota", "SD"),TENNESSEE("Tennessee", "TN"),TEXAS("Texas", "TX"),UTAH("Utah", "UT"),VERMONT("Vermont", "VT"),VIRGINIA("Virginia", "VA"),WASHINGTON("Washington", "WA"),WEST_VIRGINIA("West Virginia", "WV"),WISCONSIN("Wisconsin", "WI"),WYOMING("Wyoming", "WY"),UNKNOWN("Unknown", "UK");private String stateName;private String stateAbbreviation;State(final String newStateName, final String newStateAbbreviation){this.stateName = newStateName;this.stateAbbreviation = newStateAbbreviation;}public String getStateName(){return this.stateName;}public String getStateAbbreviation(){return this.stateAbbreviation;}public static State fromAbbreviation(final String candidateAbbreviation){State match = UNKNOWN;if (candidateAbbreviation != null && candidateAbbreviation.length() == 2){final String upperAbbreviation = candidateAbbreviation.toUpperCase();for (final State state : State.values()){if (state.stateAbbreviation.equals(upperAbbreviation)){match = state;}}}return match;} }我們還可以提供上面顯示的getSerializer()方法返回的TypeSerializer接口的實現。 通常,通過擴展org.apache.cassandra.serializers package中Cassandra提供的TypeSerializer的眾多現有實現之一,通常可以最容易地編寫實現TypeSerializer類。 在我的示例中,我的自定義序列化程序擴展了AbstractTextSerializer ,我需要添加的唯一方法是簽名public void validate(final ByteBuffer bytes) throws MarshalException 。 我的兩個自定義類都需要通過靜態訪問提供對自身實例的引用。 這是通過AbstractTypeSerializer擴展實現TypeSerializer的類:
UnitedStatesStateSerializer.java –實現TypeSerializer
package dustin.examples.cassandra.cqltypes;import org.apache.cassandra.serializers.AbstractTextSerializer; import org.apache.cassandra.serializers.MarshalException;import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets;/*** Serializer for UnitedStatesState.*/ public class UnitedStatesStateSerializer extends AbstractTextSerializer {public static final UnitedStatesStateSerializer instance = new UnitedStatesStateSerializer();private UnitedStatesStateSerializer(){super(StandardCharsets.UTF_8);}/*** Validates provided ByteBuffer contents to ensure they can* be modeled in the UnitedStatesState Cassandra/CQL data type.* This allows for a full state name to be specified or for its* two-digit abbreviation to be specified and either is considered* valid.** @param bytes ByteBuffer whose contents are to be validated.* @throws MarshalException Thrown if provided data is invalid.*/@Overridepublic void validate(final ByteBuffer bytes) throws MarshalException{try{final String stringFormat = new String(bytes.array()).toUpperCase();final State state = stringFormat.length() == 2? State.fromAbbreviation(stringFormat): State.valueOf(stringFormat);}catch (Exception exception){throw new MarshalException("Invalid model cannot be marshaled as UnitedStatesState.");}} }編寫了用于創建自定義CQL數據類型的類后,需要將它們編譯為.class文件并存檔在JAR文件中。 此過程(使用javac -cp "C:\Program Files\DataStax Community\apache-cassandra\lib\*" -sourcepath src -d classes src\dustin\examples\cassandra\cqltypes\*.java ,并將生成的歸檔.class下面的屏幕快照中顯示了將.class文件轉換為名為jar cvf CustomCqlTypes.jar *名為CustomCqlTypes.jar的JAR。
帶有自定義CQL類型類的類定義的JAR需要放置在Cassandra安裝的lib目錄中,如下一個屏幕快照所示。
通過在Cassandra安裝目錄的lib目錄中包含自定義CQL數據類型類實現的JAR,應該重新啟動Cassandra,以便它能夠“看到”這些自定義數據類型定義。
下一個代碼清單顯示了一個Cassandra查詢語言(CQL)語句,該語句用于使用新的自定義類型dustin.examples.cassandra.cqltypes.UnitedStatesState創建表。
createAddress.cql
CREATE TABLE us_address (id uuid,street1 text,street2 text,city text,state 'dustin.examples.cassandra.cqltypes.UnitedStatesState',zipcode text,PRIMARY KEY(id) );下一個屏幕快照通過描述cqlsh中創建的表來演示運行上述createAddress.cql代碼的結果。
上面的屏幕快照演示了自定義類型dustin.examples.cassandra.cqltypes.UnitedStatesState是us_address表的state列的類型。
可以使用常規INSERT將新行添加到US_ADDRESS表中。 例如,以下屏幕快照演示了使用INSERT INTO us_address (id, street1, street2, city, state, zipcode) VALUES (blobAsUuid(timeuuidAsBlob(now())), '350 Fifth Avenue', '', 'New York', 'New York', '10118');命令INSERT INTO us_address (id, street1, street2, city, state, zipcode) VALUES (blobAsUuid(timeuuidAsBlob(now())), '350 Fifth Avenue', '', 'New York', 'New York', '10118'); :
請注意,雖然INSERT語句為該州插入了“紐約”,但它存儲為“ NY”。
如果我運行一個INSERT陳述cqlsh使用縮寫下手( INSERT INTO us_address (id, street1, street2, city, state, zipcode) VALUES (blobAsUuid(timeuuidAsBlob(now())), '350 Fifth Avenue', '', 'New York', 'NY', '10118'); ),它仍然可以正常工作,如下圖所示。
在我的示例中,無效狀態不會阻止INSERT的發生,而是將狀態持久保存為“ UK”(對于未知狀態)[請參見UnitedStatesState.getStateAbbreviationAsByteBuffer(String)的實現UnitedStatesState.getStateAbbreviationAsByteBuffer(String) 。
證明為什么要在Java中實現自定義CQL數據類型的第一個優點就是,能夠采用與關系數據庫中的檢查約束所提供的行為類似的行為。 例如,在這篇文章中,我的示例確保為新行輸入的任何州列都是美國的五十個州,哥倫比亞特區或未知的“英國”之一。 不能在該列的值中插入其他值。
自定義數據類型的另一個優點是能夠將數據整理成首選格式。 在此示例中,我將每個州名稱都更改為大寫的兩位數縮寫。 在其他情況下,我可能想要始終以大寫形式存儲或始終以小寫形式存儲或將有限的字符串集映射為數值。 自定義CQL數據類型允許自定義驗證和Cassandra數據庫中值的表示。
結論
這篇文章介紹了如何在Cassandra中實現自定義CQL數據類型。 隨著我越來越多地使用這個概念并嘗試不同的方法,我希望就我所做的一些更細微的觀察撰寫另一篇博客文章。 如本文所顯示,編寫和使用自定義CQL數據類型非常容易,特別是對于Java開發人員而言。
翻譯自: https://www.javacodegeeks.com/2014/07/custom-cassandra-data-types.html
總結
以上是生活随笔為你收集整理的自定义Cassandra数据类型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JBoss Wildfly 8.1上的H
- 下一篇: vcf安卓无法打开怎么办(vcf安卓)